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 have a small function as follows:
def write_snapshot_backup_monitoring_values():
try:
snapshot_backup_result = 'my result'
with open(config.MONITOR_SNAPSHOT_BACKUP_FILE, "w") as snapshot_backup_file:
snapshot_backup_file.write(snapshot_backup_result)
except Exception as exception:
LOG.exception(exception)
where config.MONITOR_SNAPSHOT_BACKUP_FILE is declared in a config file with value = /home/result.log
when I try to write a test case using pytest and I call this function as follows:
constants.MONITOR_SNAPSHOT_BACKUP_FILE = "/tmp/result.log"
#pytest.mark.functional_test
def test_write_snapshot_backup_monitoring_values():
utils.write_snapshot_backup_monitoring_values()...
I want to monkey patch the value for config.MONITOR_SNAPSHOT_BACKUP_FILE with constants.MONITOR_SNAPSHOT_BACKUP_FILE which I have declared in the test case file. Basically I want that while runnning the test case it should create /tmp/result.log and not /home/result.log How can I do that? I am new to monkey patching in python.
You don't clear up what config is, so I assume it is another module you have imported. There's no specific technique for monkey-patching, you just assign the value. It's just a name for adding/modifying attributes at runtime.
config.MONITOR_SNAPSHOT_BACKUP_FILE = constants.MONITOR_SNAPSHOT_BACKUP_FILE
However, there's one thing to keep in mind here: Python caches imported modules. If you change this value, it will change for other python modules that have imported config and run in the same runtime. So, be careful that you don't cause any side effects.
I want to restrict the import of some modules in Python 3 (but for the scope of this question let's say that I want to restrict any import). This is the way I am trying to do it:
def __import__(self, *args, **kwrgs):
raise ImportError("Imports are not allowed")
import math
print math.sqrt(4)
It is my understanding that this should raise exception, and it is based on that document - https://docs.python.org/3/reference/import.html#importsystem that says
The search operation of the import statement is defined as a call to the __import__() function, with the appropriate arguments.
However, it does not. I would greatly appreciate an explanation as to why and suggestions how to accomplish my goal
The statement import module_name calls the builtin function __import__ with the parameter 'module_name'. It doesn't, and in fact can't, call module_name.__import__() as you expected, because the module itself hasn't been loaded yet.
A nice way to achieve what you want is to check the __name__ global variable in the non importable module. when it is run, it should be equal to '__main__', but when it is imported, it would be some other string constructed from its name. Therefore you can try:
if __name__ != '__main__':
raise ImportError("Imports are not allowed")
You had a misunderstanding: the docs are not suggesting to define your own __import__ function within the module. What they are trying to say is that when you have an import statement like
import mymodule
then the way in which the name mymodule is resolved here is by calling the built-in function __import__ in this manner:
__import__('mymodule')
If you want to prevent a module from being imported successfully, you can just put any syntax error in there, e.g. putting this as first lines in the file:
# my_unimportable_file.py
error error error
I'm trying to dynamically update code during runtime by reloading modules using importlib.reload. However, I need a specific module variable to be set before the module's code is executed. I could easily set it as an attribute after reloading but each module would have already executed its code (e.g., defined its default arguments).
A simple example:
# module.py
def do():
try:
print(a)
except NameError:
print('failed')
# main.py
import module
module.do() # prints failed
module.a = 'succeeded'
module.do() # prints succeeded
The desired pseudocode:
import_module_without_executing_code module
module.initialise(a = 'succeeded')
module.do()
Is there a way to control module namespace initialisation (like with classes using metaclasses)?
It's not usually a good idea to use reload other than for interactive debugging. For example, it can easily create situations where two objects of type module.A are not the same type.
What you want is execfile. Pass a globals dictionary (you don't need an explicit locals dictionary) to keep each execution isolated; anything you store in it ahead of time acts exactly like the "pre-set" variables you want. If you do want to have a "real" module interface change, you can have a wrapper module that calls (or just holds as an attribute) the most recently loaded function from your changing file.
Of course, since you're using Python 3, you'll have to use one of the replacements for execfile.
Strictly speaking, I don't believe there is a way to do what you're describing in Python natively. However, assuming you own the module you're trying to import, a common approach with Python modules that need some initializing input is to use an init function.
If all you need is some internal variables to be set, like a in you example above, that's easy: just declare some module-global variables and set them in your init function:
Demo: https://repl.it/MyK0
Module:
## mymodule.py
a = None
def do():
print(a)
def init(_a):
global a
a = _a
Main:
## main.py
import mymodule
mymodule.init(123)
mymodule.do()
mymodule.init('foo')
mymodule.do()
Output:
123
foo
Where things can get trickier is if you need to actually redefine some functions because some dynamic internal something is dependent on the input you give. Here's one solution, borrowed from https://stackoverflow.com/a/1676860. Basically, the idea is to grab a reference to the current module by using the magic variable __name__ to index into the system module dictionary, sys.modules, and then define or overwrite the functions that need it. We can define the functions locally as inner functions, then add them to the module:
Demo: https://repl.it/MyHT/2
Module:
## mymodule.py
import sys
def init(a):
current_module = sys.modules[__name__]
def _do():
try:
print(a)
except NameError:
print('failed')
current_module.do = _do
I am having problem understand the sys.stdout and sys.stderr
The problem is how did the variable put get got into the cmd module?
My aim is to write a single function that would accept a string basically I am using it to write exception caught in my application to the screen and to a log file. I saw similar code somewhere so I decided to learn more by using the same example i saw which was a little different from my as the other person was writing to tow files simultaneously with just one function call.
According to my understanding:
The cmd module recieves a string which it then calls output module on the recieved string.
output module takes two arguements - (1 of its parameters must evalute to python standard input module object and second the a string) fine.
However, since output module calls logs module which does the printing or better still combines parameters by calling write function from python's standard output object passing it the string or text to be written.
Please if my explanation is not clear it means I am truely not understanding the whole process.
My questions is: How does put variable called outside the function got into the cmd module or any other module when I have commented it or not even called out?
Please find code below
`
import sys
def logs(prints, message):
#global put
#print prints
prints.write(message)
prints.flush()
def output(prints, message):
#global put
#logs(prints, content)
logs(prints, message)
#logs(put, via)
''' This is where the confusion is, how did put get into this function when i did
not declare it...'''
def cmd(message):
#global put
output(put, message)
output(sys.stderr, message)
put = open('think.txt', 'w')
#print put, '000000000'
cmd('Write me out to screen/file')
put.close()
`
Its because of the way that python handles scopes. When you execute the script, the logs, output and cmd functions are defined in the module namespace. Then put = open('think.txt', 'w') creates a variable called put in the module namespace.
When you call cmd, you are now executing in the function's local namespace. it is created when the function is called and destroyed when the function exits. When python hits the expression output(put, message), it needs to resolve the names output, put and message to see what to do with them. The rules for a function are that python will look for the name in the local function namespace and then fall back to the global module namespace if the variable is not found.
So, python checks the function namespace for output, doesn't find anything, looks at the module namespace and finds that output refers to a function object. It then checks the function namespace for put, doesn't find anything, looks at the module namespace and finds that put refers to an open file object. Finally, it looks up message, finds it in the function namespace (the function parameters go into the function namespace) and off it goes.
put is declared as a global variable, so when you access it from within cmd, it is accessing that global variable without you needing to declare it within the function.
For example, this code prints 5 for the same reason:
def foo():
print "bar: {0}".format(bar)
bar = 5
foo()