I've run into a bit of a wall importing modules in a Python script. I'll do my best to describe the error, why I run into it, and why I'm tying this particular approach to solve my problem (which I will describe in a second):
Let's suppose I have a module in which I've defined some utility functions/classes, which refer to entities defined in the namespace into which this auxiliary module will be imported (let "a" be such an entity):
module1:
def f():
print a
And then I have the main program, where "a" is defined, into which I want to import those utilities:
import module1
a=3
module1.f()
Executing the program will trigger the following error:
Traceback (most recent call last):
File "Z:\Python\main.py", line 10, in <module>
module1.f()
File "Z:\Python\module1.py", line 3, in f
print a
NameError: global name 'a' is not defined
Similar questions have been asked in the past (two days ago, d'uh) and several solutions have been suggested, however I don't really think these fit my requirements. Here's my particular context:
I'm trying to make a Python program which connects to a MySQL database server and displays/modifies data with a GUI. For cleanliness sake, I've defined the bunch of auxiliary/utility MySQL-related functions in a separate file. However they all have a common variable, which I had originally defined inside the utilities module, and which is the cursor object from MySQLdb module.
I later realised that the cursor object (which is used to communicate with the db server) should be defined in the main module, so that both the main module and anything that is imported into it can access that object.
End result would be something like this:
utilities_module.py:
def utility_1(args):
code which references a variable named "cur"
def utility_n(args):
etcetera
And my main module:
program.py:
import MySQLdb, Tkinter
db=MySQLdb.connect(#blahblah) ; cur=db.cursor() #cur is defined!
from utilities_module import *
And then, as soon as I try to call any of the utilities functions, it triggers the aforementioned "global name not defined" error.
A particular suggestion was to have a "from program import cur" statement in the utilities file, such as this:
utilities_module.py:
from program import cur
#rest of function definitions
program.py:
import Tkinter, MySQLdb
db=MySQLdb.connect(#blahblah) ; cur=db.cursor() #cur is defined!
from utilities_module import *
But that's cyclic import or something like that and, bottom line, it crashes too. So my question is:
How in hell can I make the "cur" object, defined in the main module, visible to those auxiliary functions which are imported into it?
Thanks for your time and my deepest apologies if the solution has been posted elsewhere. I just can't find the answer myself and I've got no more tricks in my book.
Globals in Python are global to a module, not across all modules. (Many people are confused by this, because in, say, C, a global is the same across all implementation files unless you explicitly make it static.)
There are different ways to solve this, depending on your actual use case.
Before even going down this path, ask yourself whether this really needs to be global. Maybe you really want a class, with f as an instance method, rather than just a free function? Then you could do something like this:
import module1
thingy1 = module1.Thingy(a=3)
thingy1.f()
If you really do want a global, but it's just there to be used by module1, set it in that module.
import module1
module1.a=3
module1.f()
On the other hand, if a is shared by a whole lot of modules, put it somewhere else, and have everyone import it:
import shared_stuff
import module1
shared_stuff.a = 3
module1.f()
… and, in module1.py:
import shared_stuff
def f():
print shared_stuff.a
Don't use a from import unless the variable is intended to be a constant. from shared_stuff import a would create a new a variable initialized to whatever shared_stuff.a referred to at the time of the import, and this new a variable would not be affected by assignments to shared_stuff.a.
Or, in the rare case that you really do need it to be truly global everywhere, like a builtin, add it to the builtin module. The exact details differ between Python 2.x and 3.x. In 3.x, it works like this:
import builtins
import module1
builtins.a = 3
module1.f()
As a workaround, you could consider setting environment variables in the outer layer, like this.
main.py:
import os
os.environ['MYVAL'] = str(myintvariable)
mymodule.py:
import os
myval = None
if 'MYVAL' in os.environ:
myval = os.environ['MYVAL']
As an extra precaution, handle the case when MYVAL is not defined inside the module.
This post is just an observation for Python behaviour I encountered. Maybe the advices you read above don't work for you if you made the same thing I did below.
Namely, I have a module which contains global/shared variables (as suggested above):
#sharedstuff.py
globaltimes_randomnode=[]
globalist_randomnode=[]
Then I had the main module which imports the shared stuff with:
import sharedstuff as shared
and some other modules that actually populated these arrays. These are called by the main module. When exiting these other modules I can clearly see that the arrays are populated. But when reading them back in the main module, they were empty. This was rather strange for me (well, I am new to Python). However, when I change the way I import the sharedstuff.py in the main module to:
from globals import *
it worked (the arrays were populated).
Just sayin'
A function uses the globals of the module it's defined in. Instead of setting a = 3, for example, you should be setting module1.a = 3. So, if you want cur available as a global in utilities_module, set utilities_module.cur.
A better solution: don't use globals. Pass the variables you need into the functions that need it, or create a class to bundle all the data together, and pass it when initializing the instance.
The easiest solution to this particular problem would have been to add another function within the module that would have stored the cursor in a variable global to the module. Then all the other functions could use it as well.
module1:
cursor = None
def setCursor(cur):
global cursor
cursor = cur
def method(some, args):
global cursor
do_stuff(cursor, some, args)
main program:
import module1
cursor = get_a_cursor()
module1.setCursor(cursor)
module1.method()
Since globals are module specific, you can add the following function to all imported modules, and then use it to:
Add singular variables (in dictionary format) as globals for those
Transfer your main module globals to it
.
addglobals = lambda x: globals().update(x)
Then all you need to pass on current globals is:
import module
module.addglobals(globals())
Since I haven't seen it in the answers above, I thought I would add my simple workaround, which is just to add a global_dict argument to the function requiring the calling module's globals, and then pass the dict into the function when calling; e.g:
# external_module
def imported_function(global_dict=None):
print(global_dict["a"])
# calling_module
a = 12
from external_module import imported_function
imported_function(global_dict=globals())
>>> 12
The OOP way of doing this would be to make your module a class instead of a set of unbound methods. Then you could use __init__ or a setter method to set the variables from the caller for use in the module methods.
Update
To test the theory, I created a module and put it on pypi. It all worked perfectly.
pip install superglobals
Short answer
This works fine in Python 2 or 3:
import inspect
def superglobals():
_globals = dict(inspect.getmembers(
inspect.stack()[len(inspect.stack()) - 1][0]))["f_globals"]
return _globals
save as superglobals.py and employ in another module thusly:
from superglobals import *
superglobals()['var'] = value
Extended Answer
You can add some extra functions to make things more attractive.
def superglobals():
_globals = dict(inspect.getmembers(
inspect.stack()[len(inspect.stack()) - 1][0]))["f_globals"]
return _globals
def getglobal(key, default=None):
"""
getglobal(key[, default]) -> value
Return the value for key if key is in the global dictionary, else default.
"""
_globals = dict(inspect.getmembers(
inspect.stack()[len(inspect.stack()) - 1][0]))["f_globals"]
return _globals.get(key, default)
def setglobal(key, value):
_globals = superglobals()
_globals[key] = value
def defaultglobal(key, value):
"""
defaultglobal(key, value)
Set the value of global variable `key` if it is not otherwise st
"""
_globals = superglobals()
if key not in _globals:
_globals[key] = value
Then use thusly:
from superglobals import *
setglobal('test', 123)
defaultglobal('test', 456)
assert(getglobal('test') == 123)
Justification
The "python purity league" answers that litter this question are perfectly correct, but in some environments (such as IDAPython) which is basically single threaded with a large globally instantiated API, it just doesn't matter as much.
It's still bad form and a bad practice to encourage, but sometimes it's just easier. Especially when the code you are writing isn't going to have a very long life.
I am trying to better understand Pythons modules, coming from C background mostly.
I have main.py with the following:
def g():
print obj # Need access to the object below
if __name__ == "__main__":
obj = {}
import child
child.f()
And child.py:
def f():
import main
main.g()
This particular structure of code may seem strange at first, but rest assured this is stripped from a larger project I am working on, where delegation of responsibility and decoupling forces the kind of inter-module function call sequence you see.
I need to be able to access the actual object I create when first executing main python main.py. Is this possible without explicitly sending obj as parameter around? Because I will have other variables and I don't want to send these too. If desperate, I can create a "state" object for the entire main module that I need access to, and send it around, but even that is to me a last resort. This is global variables at its simplest in C, but in Python this is a different beast I suppose (module global variables only?)
One of the solutions, excluding parameter passing at least, has turned to revolve around the fact that when executing the main Python module main as such - via f.e. python main.py where if clause suceeds and subsequently, obj is bound - the main module and its state exist and are referenced as __main__ (inspected using sys.modules dictionary). So when the child module needs the actual instance of the main module, it is not main it needs to import but __main__, otherwise two distinct copies would exist, with their own distinct states.
'Fixed' child.py:
def f():
import __main__
__main__.g()
I'm pretty new to Python as to OOP in general which is probably be the reason that I can't figure out the following:
I'm writing a python script which opens a text file and subsequently translates it into HTML, maintaining it's "own" mirrored directory-trees for the edit files and the html files.
Since directory creation and deletion is done automatically depending on, among other criteria, whether the file existed before or not, I need some kind of automatic and dynamic path adjustment. The script has to do several checks for files and associated directories before it can set the corresponding paths and start the processing.
I decided to put most of the more general functions (check file existence, show dialogs for duplicate filenames if found, etc) in a separate module, since they are quite specific and not depending on any state. Actually they create the state (path variables), so a class would not make sense if this is not a misconception.
On the other hand I'm using a class for the pure getting and setting the paths since I need the paths accessible from every module, so it's basically a global access point for paths.
This class is instantiated in the main module.
Now my problem is that I can't figure out how to manipulate the paths (using the path
setters) of that instance in the main module from a function inside the tools module. Importing the class instance or the main module into the tools module doesn't seem to work.
Generally speaking, is it possible to use a class instance across all module files and is this the way to go, or am I missing the point somehow?
I paste the relevant bits of code for illustration:
Setter/Getter class inside the main module
class SetEnv():
def __init__(self):
pass
def set_path_srcfile(self, path_srcfile):
self.path_srcfile = path_srcfile
def set_path_htmlfile(self):
self.path_htmlfile = self.path_srcfile.replace('source', 'html', 1).replace('.txt', '.html', 1)
def get_path_srcfile(self):
return self.path_srcfile
def get_path_htmlfile(self):
return self.path_htmlfile
Later in main_module:
env = SetEnv()
Part of tools module (inside a def acting upon user input):
import main_module as mm
path_srcfile = dict[int(user_option)][1] # dictionary holding the path we want to set
mm.env.set_path_srcfile(path_srcfile)
mm.env.set_path_htmlfile()
I might be misinterpreting your question, correct me if I am. As I understand it, you are using one single instance of a SetEnv object across an entire project to store and modify some path configuration.
If you really want a singleton like settings object, then use a module instead of a class.
# env.py
_src = ''
_html = ''
def set_path_srcfile(path_srcfile):
global _src
_src = path_srcfile
def get_path_srcfile():
return _src
...
Then everywhere you need it you can use import env; env.set_path_srcfile(myfile) and know that all other functions / modules / classes will be aware of the update.
If you don't want a singleton, then making a settings object available in the main module somewhere (as you have done) is a fine solution.
I'm a python newbie, and developing my first python app using the CherryPy Web Server and Jinja 2 Templating engine.
I'm using a Velleman K8055 USB experiment board, which has a python module that I'm importing.
For the K8055 to function properly I have to create an instance of the class within the K8055 module, then open a connection to the board... As far as I understand it I have to keep that connection/instance running, and use that sole instance to control the board, even from within sub-modules.
I'm having a hard time figuring out how to access the previously initialised instance of the K8055 from within my sub-modules/packages...
I have a Application structure very similar to the following...
SmartyPi/
SmartyPi/smartypi.py
SmartyPi/smartypi/__init__.py
SmartyPi/smartypi/scheduler/
SmartyPi/smartypi/scheduler/__init__.py
SmartyPi/smartypi/scheduler/Scheduler.py
SmartyPi/smartypi/web/
SmartyPi/smartypi/web/__init__.py
SmartyPi/smartypi/web/k8055.py
SmartyPi/smartypi/web/root.py
SmartyPi/smartypi/web/schedule.py
In 'SmartyPi/smartypi.py' I have initialised my instance of the k8055 object with:
from pyk8055 import k8055
k = k8055(0)
I'd like to be able to access the same instance of 'k' from places like:
SmartyPi/smartypi/web/k8055.py
SmartyPi/smartypi/web/schedule.py
I can't seem to figure it out on my own...
Was 'SmartyPi/smartypi.py' not the best place to create my K8055 instance?
Should I be making it somewhere else, and how can I make this work as I need it to?
Add k = k8055(0) to the pyk8055 module (at the end). An than in all other modules just replace:
from pyk8055 import k8055
with
from pyk8055 import k
Note: I suggest to rename k with something more unique.
In case you cannot edit puk8055 module, create your own, call it i.e. globals.py:
from pyk8055 import k8055
k = k8055(0)
After that in other modules instead directly importing pyk8055, just import your module globals.py:
from globals import k
I have tasked to modify a wx python gui based program which has several .py files.
I would like to share some variables defined in a.py and use them in b.py
The 10 -15 variables are of this form:
Amode = [SINGLE]
Format = [A] etc...
I would like to use them in b.py.
How do I go about it? I read about Pickle but still not clear how to use it well.
import a
// do something with a.Amode
// do something with a.Format
Generally, the best idea, in this case, is to either place the variables on the module directly or use some shared dataStore. I like the Borg pattern for this.
Basically do this:
#in borg.py
class Borg:
__shared_state = {}
def __init__(self):
self.__dict__ = self.__shared_state
Everywhere else:
import borg
drone = borg.Borg()
drone.foo = 1;
Obviously, you can limit this by defining __set__.
As to placing variables on modules directly, well, I'm not really a fan of having stateful variables publicly accessible on modules, but that is probably mostly me.
Modules are singletons (no matter how many times it's imported, it's only actually imported once, and that once is shared), so what I often do for this use case is to create a modules named, say, "shared.py", and put the data I want shared across other modules in it. Then, in those other modules:
import shared
# Use a shared variable/object
print shared.Amode
# Changes to the shared data are seen in all modules where it's imported.
shared.Amode = aNewValue
This has the nice effect of keeping all my shared data in its own namespace, "shared".