0

I have one python file which is responsible for optionparsing, setting up some stuff and then starting the gui. The gui itself and some helper functions are in another python file.

file1.py:

myConf = None

if __name__ == "__main__":
    confFileName = HOME+"/test/.conf"    
    myConf = Config()
    print(myConf)    # works as expected

    run()    # this starts the gui

file2.py

from file1 import myConf

...somestuff...
    def on_clicked( self, widget ):
        mappings = myConf.GetMappings()

As soon as the on_clicked callback is triggered I get an exception:

AttributeError: 'NoneType' object has no attribute 'GetMappings'

This means the myConf which is used in file2 is not yet initialized. However, the gui is set up AFTER myCOnf has been initialized in file1. I want myConf to be a global object which stores information which then every other file can access during runtime.

Whats wrong? Why is it not working as intended?

Has file2 its own copy of the symbol whoch has not been initialized?

lugge86
  • 255
  • 3
  • 11
  • Circular import. Don't do that, especially when one of the files involved is your main script - `__main__` is weird. Provide `myConf` to `file2.py` in a way that doesn't involve circular imports. – user2357112 Apr 12 '17 at 17:14
  • The code under `if __name__ == "__main__":` gets executed only if you launch file1.py as your main script. If you `import file1`, it won't execute. – Thierry Lathuille Apr 12 '17 at 17:14
  • In `file2` you're creating a *new* reference to whatever `myConf` was at the time of import. Changing the reference in the `file1` module won't affect that binding. Similar to [pass a variable by reference](http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference). – Mark Ransom Apr 12 '17 at 17:17

1 Answers1

0

When you run file1.py directly, the code under __name__ == "__main__" is executed, initializing myConf and working as expected. However, when you do from file1 import myConf, file1.py is not the main script and, therefore, leaves myConf at the None that it was initialized to. Therefore, when you import myConf, its value is None and raises the error that the None has no attribute getMappings. It doesn't have this attribute, so the error is meant to be raised.

To fix this, you need to move the initializing script out of the if __name__ == "__main__". This leaves your script looking like this:

myConf = None

confFileName = HOME+"/test/.conf"    
myConf = Config()

if __name__ == "__main__":
    print(myConf)

    run()    # this starts the gui
  • OK I understand this. It's working now. However, assuming Config() takes a parameter for initialization, say, the filename of a configfile which needs to be extraced from argv, where do I do all this extracting and formatting of the filename? – lugge86 Apr 12 '17 at 18:51
  • Seems weird. From an architecture point-of-view I want to separate between cli-option-parsing and configfile parsing. But OK I will do so for now. However, next problem: the constructor of class Config is now being executed multiple times (once for every file which imports this symbol). Thats bad. I just want a way to share data between files, like, a C-style forward declaration. "Hi gui, somewhere out there is myConf, no need to do anything, just use the already-existing Config-object". Just a simple global data blob... – lugge86 Apr 12 '17 at 19:21
  • Nevermind. I just learned the difference between "import abc" and "from abc import *"..... – lugge86 Apr 12 '17 at 20:10