Importing values in config.py - python

I wanted to mix a config.py approach and ConfigParser to set some default values in config.py which could be overridden by the user in its root folder:
import ConfigParser
import os
CACHE_FOLDER = 'cache'
CSV_FOLDER = 'csv'
def main():
cp = ConfigParser.ConfigParser()
cp.readfp(open('defaults.cfg'))
cp.read(os.path.expanduser('~/.python-tools.cfg'))
CACHE_FOLDER = cp.get('folders', 'cache_folder')
CSV_FOLDER = cp.get('folders', 'csv_folder')
if __name__ == '__main__':
main()
When running this module I can see the value of CACHE_FOLDER being changed. However when in another module I do the following:
import config
def main()
print config.CACHE_FOLDER
This will print the original value of the variable ('cache').
Am I doing something wrong ?

The main function in the code you show only gets run when that module is run as a script (due to the if __name__ == '__main__' block). If you want that turn run any time the module is loaded, you should get rid of that restriction. If there's extra code that actually does something useful in the main function, in addition to setting up the configuration, you might want to split that part out from the setup code:
def setup():
# the configuration stuff from main in the question
def main():
# other stuff to be done when run as a script
setup() # called unconditionally, so it will run if you import this module
if __name__ == "__main__":
main() # this is called only when the module is run as a script

Related

Python relative import variable name error [duplicate]

I created two files, and when I run a.py, result is {'1': '1'}, it's correct. however, running b.py, the result is none. How can I get the value of requests from b.py?
a.py:
requests = {}
def set_value():
global requests
requests["1"] = "1"
if __name__ == "__main__":
set_value()
print(requests)
b.py:
import a
def get_value():
print(a.requests)
if __name__ == "__main__":
get_value()
if __name__ == "__main__": means that the code following it will only be executed when the file is called explicitly with python3 filename.py from the command line. Since you are simply importing your file and not executing it, the global variable is never set.
Also, python variables are all "global" variables when declared outside of a function, and the global keyword is only needed when you want to declare a global variable inside of a function.
To fix this, change a.py to the following:
requests = {}
def set_vale():
requests["1"] = "1"
set_vale()

Why do so many people put the app.run() in flask sites into a __name__ == "__main__" condition?

I know what if __name__ == "__main__" does and use it, but why do so many people and the documentation put the " app.run() " function of flask in this condition?
This is because there are certain situation where you have to access certain variables for example when you have a sqlalchemy database and If you want create tables. You have to do
from app import db
In such situation you app will run
Also when you move to production you don't need run and app is called from elsewhere if you add if __name__ == "__main__" part run will not be called unnecessarly.
This will ensure that when this module is imported, it won't run the code within
if __name__ == "__main__":
Your name == "main" when you run the .py directly.
ex:
foo.py
import bar
print("This is foo file)
now the inverse:
bar.py
import foo
def main():
print(This is bar file)
print(__name__)
if __name__ == "__main__":
main()
(running the bar.py file)
python bar.py
This is foo file
This is bar file
"__main__"
(running the foo.py file)
python foo.py
this is foo file
I know others will comment and provide a more thorough answer. But this is one way of looking at it.
Cheers.

Global variable sharing across different modules behave differently

In config.py, I have:
config = 0
#config = []
def init_config():
global config
config = 1
#config.append("1")
print("init", config)
In main.py, I have:
from config import init_config
from config import config
def main():
init_config()
print("main", config)
if __name__ == '__main__':
main()
And both the config.py and the main.py in the same directory. After running python main.py, I got:
init 1
main 0
But if I use the comment lines in the config.py instead, I got:
init ['1']
main ['1']
So why does the difference happen? (Python 3.5.5)
Once imported from config.py, the variable config becomes a separate copy of config.config that lives in main.py's namespace. You should import config as a module and then access the variable config as an attribute to the module config instead:
import config
def main():
config.init_config()
print("main", config.config)
if __name__ == '__main__':
main()

symbol has wrong value after import

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?
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

if __name__ == '__main__' function call

I am trying to work around a problem I have encountered in a piece of code I need to build on. I have a python module that I need to be able to import and pass arguments that will then be parsed by the main module. What I have been given looks like this:
#main.py
if __name__ == '__main__'
sys.argv[] #pass arguments if given and whatnot
Do stuff...
What I need is to add a main() function that can take argument(s) and parse them and then pass them on like so:
#main.py with def main()
def main(args):
#parse args
return args
if __name__ == '__main__':
sys.argv[] #pass arguments if given and whatnot
main(sys.argv)
Do stuff...
To sum up: I need to import main.py and pass in arguments that are parsed by the main() function and then give the returned information to the if __name_ == '__main_' part.
EDIT
To clarify what I am doing
#hello_main.py
import main.py
print(main.main("Hello, main"))
ALSO I want to still be able to call main.py from shell via
$: python main.py "Hello, main"
Thus preserving the name == main
Is what I am asking even possible? I have been spending the better part of today researching this issue because I would like to, if at all possible, preserve the main.py module that I have been given.
Thanks,
dmg
Within a module file you can write if __name__ == "__main__" to get specific behaviour when calling that file directly, e.g. via shell:
#mymodule.py
import sys
def func(args):
return 2*args
#This only happens when mymodule.py is called directly:
if __name__ == "__main__":
double_args = func(sys.argv)
print("In mymodule:",double_args)
One can then still use the function when importing to another file:
#test.py
import mymodule
print("In test:",mymodule.func("test "))
Thus, calling python test.py will result in "In test: test test ", while calling python mymodule.py hello will result in "In mymodule: hello hello ".

Categories

Resources