What should I name my global module in Python? - python

I'm writing an application in Python, and I've got a number of universal variables (such as the reference to the main window, the user settings, and the list of active items in the UI) which have to be accessible from all parts of the program1. I only just realized I've named the module globals.py and I'm importing the object which contains those variables with a from globals import globals statement at the top of my files.
Obviously, this works, but I'm a little leery about naming my global object the same as the Python builtin. Unfortunately, I can't think of a much better naming convention for it. global and all are also Python builtins, universal seems imprecise, state isn't really the right idea. I'm leaning towards static or env, although both have a specific meaning in computer terms which suggests a different concept.
So, what (in Python) would you call the module which contains variables global to all your other modules?
1 I realize I could pass these (or the single object containing them) as a variable into every other function I call. This ends up being infeasible, not just because it makes the startup code and function signatures really ugly.

I would try to avoid such a global container module altogether, and instead put these variables into their own modules, which can then be imported from all parts of the system.
For example, the main window would probably go into a variable in main.py. User settings could go into usersettings.py which would provide functions to view and change the settings.
If another part of the system needs to access the user settings, that's a simple matter of:
from usersettings import get_setting, set_setting
...
# Do stuff with settings
A similar approach could probably be used for other stuff that needs to be globally accessible. This leads to clearer separation of concerns and more testable code, since you can test modules in isolation without depending on the globals module all the time.

I'd call it env. There's little risk that someone will confuse it with os.environ (especially if you organize your code so that you can call it myapp.environ).
I'd also make everything exposed by myapp.environ a property of a class, so that I can put breakpoints in the setter when the day comes that I need to.

`config` or `settings`

top? top_level?

from globals import Globals
This will fix the conflict and also follows PEP 8 recommendations.
Also, in other cases like this, Roget's Thesaurus is your friend. I always keep a copy nearby.

global is a keyword, not a built-in. 'globals' is not a keyword, but is a built-in function. It can be assigned to, but is bad practice. Code checkers like pylint and pychecker can catch these accidental assignments. How about config?

Related

Opposite of __ALL__ in python (for excluding functions)

I'm quite sure this is a duplicate, but I can't find an answer (I must be searching the wrong terms).
The __all__ variable in python allows you to explicitly note the functions you want included on a global import. I wondered: is there a similar variable (something like __exclude__) that includes __all__ in a global import with the exception of those functions placed in __exclude__?
There are some functions I'd like sphinx to ignore for documentation, and sphinx seems to rely on __all__. But, when I implement new functionality, I'll occasionally forget to add it to __all__ which can be frustrating. It would be much easier to assume everything is to be used with the exception of a few named functions in a variable. Is this possible?
Again, sorry if this is a repeat.

How bad is it to explicitly add things to locals()?

I'm trying to dynamically load modules as explained here.
I have written a script that requires some modules that may not be installed by default on some systems (such as requests). The script code assumes that a regular import has been done (it uses requests.get).
If I use the code in the link above, to import requests I would have to use:
requests=importlib.import_module('requests')
But this leads to a lot of code duplication since I have several modules. I can't use that in a loop since the variable name must change with the imported module.
I have found that I can use:
for m in list_of_modules:
locals()[m]=importlib.import_module(m)
And everything happens as if I had done regular import's.
(of course the real code catches exceptions...).
So the question is how valid/risky this is? Too good to be true or not? (Python 2.7 if that makes a difference)
It is explicitely invalid. Doc of Python 2.7.15 says of locals() function:
The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
locals() is a way for the program to know the list of variables in a function block. It is not a way to create local variables.
If you really need something like that, you can either use a local map, rely on the sys.modules map which is updated by import_module, or update the globals() map. Anyway, once a module was loaded, it exists (through the sys.module map) for the whole program, so it does not really make sense to store its reference in a local symbol table.
So if you really need to import a dynamically builded list of modules, I would do:
for m in list_of_modules:
globals()[m]=importlib.import_module(m)

Use function globally or locally?

In Python I have several functions that use the location of the user's directory as a way of determining where to put files.
I currently use a "global" variable for all the functions to use.
home = os.path.expanduser('~')
I'm wondering if this is good coding practice.
The upside of this is that the program only needs to execute this code only once.
I could also have each function call os.path.expanduser each time it is called.
Which is the more pythonic one? Or is there a pythonicer way?
There's nothing wrong with globals. It's a consequence of how you designed your program. You wrote a few functions and put them in a module, and globals are a way to share data between individual functions in a module.
For example, had you decided to go with an object oriented design, then one could argue that globals should be avoided and shared data should be encapsulated. But you didn't do that, so globals are fine.
It is ok to use global constants. At the end all the first-level function and classes defined in the same module are also "global" in this sense.
Using gobal variables becomes messy when different components of the system start re-assigning their values or mutate their content. In this case it's an obvious antipattern and can lead to a debugging hell.

Safest way of using global variables in python: module or "global" keyword?

I have to share around 10 variables between functions, which are contained in the same .py file. The variables will be modified in almost every function. I know that global variables are evil, but unfortunately for now I have to keep few of them as global, while the rest I have been able to change the implementation and to pass them as an argument.
One way of doing this would be using the "global" keyword, but I have run into another option, that would be placing them in an empty module, and importing the module every time.
I am just a beginner in python, what would be the best way to do this?
EDIT: This is a rewriting of a code based almost completely on global variables. Almost all the functions are now in a class, the variables are used with self.name_var. However, since we are using multiprocess with Array, few variables have to remain globals.
Thanks,
Andrea
Just do not do it, put all the functions, if they are related, in a class and make the variables accessible with self. Using a different module is worst.

How to share same variable between imported modules

There are two Python scripts: master.py and to_be_imported.py
Here is the master.py:
import os
os.foo = 12345
import to_be_imported
And here is the to_be_imported.py:
import os
if hasattr(os, 'foo'):
print 'os hasattr foo: %s'%os.foo
Now when I run master.py I get this:
os hasattr foo: 12345
indicating that the imported module to_be_imported.py picks up the variable declared inside the process that imported it (master.py).
While it works fine I would like to know why it works and also to make sure it is a safe practice.
If a module is already imported, subsequent imports to the module uses the cached version of the module. Even if you reference it via different names as in the following case
import os as a
import os as b
Both refer to the same os module that was imported the first time. So it is obvious that the variable assigned to a module will be shared.
You can verify it using the built-in python function id()
Nothing is a bad idea per se, but you must remember few things:
Modules are objects in Python. They are loaded only once and added to sys.modules. These objects can also be added attributes like regular objects (with no messy implementation of setattr).
Since they are objects, but not instantiable ones, you must consider them as singletons (they are singletons, after all), and you must consider the disadvantages and benefits of such model:
a. Singletons are only one object. Are you sure that accessing their attributes is concurrency-safe?
b. Modules are global objects. Are you sure you can track the whole behavior and access to their members? Are you sure you will be able to debug errors there?
Is the code something you will work with others?
While no idea is better than other, good practices tell us that using global variables is not well-seen, specially if we have a team to work with. On the other hand: if your code is concurrent and/or reentrant, avoid using global variables or relying on module attributes. OTOH you will have no problem assigning attributes like that. They will last for the life of your script execution.
This is not the place to chose the best alternative. Depending on how you state your problem, you can ask it either on programmers or codereview. You can chose many variants to share state without using global variables in modules, like passing those variables inside a state back and forth across arguments, or learning and using OOP. But, again, this site is no scope for that.

Categories