I have a set of Python files as follows:
py-app/
main.py
module1.py
Inside main.py I declare a variable config as follows
config = {"param1": "value1", "param2":"value2"}
How can I make config variable global in order for it to be accessed in module1.py as follows:
Inside module1.py
def foo()
print(config["param1"])
Please see this from the official website:
https://docs.python.org/3/faq/programming.html#how-do-i-share-global-variables-across-modules
What you can do is - create a special module to store all the global variables there and access them by importing the module.
This singleton design pattern is followed and if you modify the state in one file it will be reflected everywhere. It basically works like a session object.
If required, you can initialize the values as well.
Related
I am currently working on a project with multiple files and created a shared variables file for all the global variables I need.
everything seemed to be working fine until I tried modifying a global variable from within a subdirectory.
the layout of my projects looks something like this:
projects/
projects/shared_variables.py
projects/main.py
-projects/logic2
projects/subDir
projects/subDir/logic.py
the code in them looks something like this:
shared_variables.py:
# this file contains all the global variables for the project
foo = "initialized"
main.py:
from myproject import shared_variables
from myproject.subDir.logic import do_something
if __name__ == '__main__':
print(f"foo variable in main:{shared_variables.foo} foo id:{id(shared_variables.foo)}")
do_something()
logic.py:
import myproject.shared_variables
def do_something():
myproject.shared_variables.foo = 5#doing something
print(f"foo variable in logic:{myproject.shared_variables.foo} logic id:{id(myproject.shared_variables.foo)}")
the output of the code is:
foo variable in main:initialized foo id:4426951216
foo variable in logic:5 logic id:4423687024
so basically when to import the foo variable and use it in any other files like logic2 which are on the same directory everything works fine and I get the same id(in this case 4426951216) but whenever I try to make changes to foo in the subdirectory (subDir) the changes don't pass for the rest of the project and by the looks of it its because logic initializes shared_variables.py again.
I have already tried defining init() function in shared_variables and calling it in main.py but in this case, i get a variable not found error(foo) only in logic.py
I was trying to define bunch fixtures in one file say redis.py (abc\plgfix\redis.py) and use them in my test cases (abc\common\test_file.py) via pytest_plugin. While doing that I notice test cases couldn't see fixtures I defined.
My Folder structure is as follows
abc
|
common
|
config.py ( I have defined pytest_plugin=["plgfix.redis"]
test_file.py
plgfix
|
redis.py ( I have defined bunch of fixtures here)
__init__.py
From above illustration
-> plgfix (folder) has my desired file(redis.py) and __init__.py file to
make folder as package.
-> In abc\common\config.py. I have defined pytest_plugin global variable
pytest_plugins = ["plgfix.redis"] #assuming all fixtures in
#redis.py file , available for test cases
-> Now I have created abc\common\test_file.py where I'm using one of the
defined fixture in redis.py (abc\plgfix\redis.py) as follows.
def test_fixtu(fix1):
print ("Hi")
pass
I was getting error as fix1 is not found
Note : I can able to import config file and see contents as 'package', 'spec', 'pytest_plugins'....... (confirming it is not path issue)
According to the pytest docs, the global var is supposed to be either a str or a Sequence[str]. You seem to have assigned a list to it.
I'm a bit confused about globals when it comes to packages using other packages. From a quick google search; there's not much that explains.
Simply put: at what level is a variable "globalized" when using global? Is it at the module level, package level, or interpreter level? Ie, in a setup such as this:
<Package>
|- __init__.py
|- Module.py
|- Module2.py
and there is a global statment used within Module.py, is the variable globalized for just that module, or the entire package (including Module2.py and or __init__.py), or at the interperter level (for anything being run in the interpreter).
Also, if in __init__.py I from .Module import *, would the imported functions containing a global statement "properly globalize" any said variable for that file?
How global are global variables?
So-called "global" variables in Python are really module-level. There are actually-global globals, which live in the __builtin__ module in Python 2 or builtins in Python 3, but you shouldn't touch those. (Also, note the presence or lack of an s. __builtins__ is its own weird thing.)
What does the global statement do?
The global statement means that, for just the function in which it appears, the specified variable name or names refer to the "global" (module-level) variable(s), rather than local variables.
What about import *?
Oh god, don't do that. Globals are bad enough, but importing them is worse, and doing it with import * is just about the worst way you could do it. What the import system does with global variables is horribly surprising to new programmers and almost never what you want.
When you do import *, that doesn't mean that your module starts looking in the imported module's global variables for variable lookup. It means that Python looks in the imported module, finds its "public" global variables*, and assigns their current values to identically-named new global variables in the current module.
That means that any assignments to your new global variables won't affect the originals, and any assignments to the originals won't affect your new variables. Any functions you imported with import * are still looking at the original variables, so they won't see changes you make to your copies, and you won't see changes they make to theirs. The results are a confusing mess.
Seriously, if you absolutely must use another module's global variables, import it with the import othermodule syntax and access the globals with othermodule.whatever_global.
*If the module defines an __all__ list, the "public" globals are the variables whose names appear in that list. Otherwise, they're the variables whose names don't start with an underscore. defined functions are stored in ordinary variables, so those get included under the same criteria as other variables.
I'm a bit confused about globals when it comes to packages using other packages. From a quick google search; there's not much that explains.
Simply put: at what level is a variable "globalized" when using global? Is it at the module level, package level, or interpreter level? Ie, in a setup such as this:
<Package>
|- __init__.py
|- Module.py
|- Module2.py
and there is a global statment used within Module.py, is the variable globalized for just that module, or the entire package (including Module2.py and or __init__.py), or at the interperter level (for anything being run in the interpreter).
Also, if in __init__.py I from .Module import *, would the imported functions containing a global statement "properly globalize" any said variable for that file?
How global are global variables?
So-called "global" variables in Python are really module-level. There are actually-global globals, which live in the __builtin__ module in Python 2 or builtins in Python 3, but you shouldn't touch those. (Also, note the presence or lack of an s. __builtins__ is its own weird thing.)
What does the global statement do?
The global statement means that, for just the function in which it appears, the specified variable name or names refer to the "global" (module-level) variable(s), rather than local variables.
What about import *?
Oh god, don't do that. Globals are bad enough, but importing them is worse, and doing it with import * is just about the worst way you could do it. What the import system does with global variables is horribly surprising to new programmers and almost never what you want.
When you do import *, that doesn't mean that your module starts looking in the imported module's global variables for variable lookup. It means that Python looks in the imported module, finds its "public" global variables*, and assigns their current values to identically-named new global variables in the current module.
That means that any assignments to your new global variables won't affect the originals, and any assignments to the originals won't affect your new variables. Any functions you imported with import * are still looking at the original variables, so they won't see changes you make to your copies, and you won't see changes they make to theirs. The results are a confusing mess.
Seriously, if you absolutely must use another module's global variables, import it with the import othermodule syntax and access the globals with othermodule.whatever_global.
*If the module defines an __all__ list, the "public" globals are the variables whose names appear in that list. Otherwise, they're the variables whose names don't start with an underscore. defined functions are stored in ordinary variables, so those get included under the same criteria as other variables.
I'm writing a module to load a dataset. I want to keep the interface/API as clean as possible - so I've made internal functions and variables hidden by prefacing their names with __. Awesome. My module, however, imports other packages (e.g. numpy) which still appear in my module's namespace, how can I avoid this?
i.e. my file looks something like:
Loader.py:
import numpy as np
__INTERNAL_VAR1 = True
EXTERNAL_VAR = True
def loadData():
data = __INTERNAL_FUNC1()
...
return data
def __INTERNAL_FUNC1():
...
return data
and when I import my module np is exposed:
> import Loader
> Loader.[TAB]
Loader.EXTERNAL_VAR Loader.loadData Loader.np
If the autocompletion you are using is correctly implemented, it should honour the __all__ attribute of modules, if set.
Add a list of all names your module exports in that name:
__all__ = ['loadData', 'EXTERNAL_VAR']
The __all__ variable is used to determine what names are imported if you use a from modulename import * wildcard import, as well as by the help() function when documenting your module.
There is no point in using double-underscore names as globals; it is a single underscore at the start that marks such names as 'internal' (by convention).
Another solution could be to create an __init__.py that contains a line that imports the functions and variables you need:
from Loader import EXTERNAL_VAR,loadData
This file should be placed inside a folder containing your module:
└── Loader
├── __init__.py
└── Loader.py
Now when you import Loader you can access directly only EXTERNAL_VAR and loadData while all the other classes and modules are in Loader.Loader.
This solution should be independent of your autocompletion system.