Visibility of global variables in imported modules

I came across a small port importing modules into a Python script. I will do my best to describe the error, why I ran into it, and why I associate this specific approach to solve my problem (which I will tell in a second):

Suppose I have a module in which I defined some utility functions / classes that relate to objects 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 these utilities:

 import module1 a=3 module1.f() 

Running the program will cause 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 

In the past, similar questions were asked (two days ago, d'u), and several solutions were proposed, however, I do not think they fit my requirements. Here is my specific context:

I am trying to make a Python program that connects to a MySQL database server and displays / modifies data using a graphical interface. For the sake of cleanliness, I have defined a bunch of auxiliary / useful functions related to MySQL in a separate file. However, they all have a common variable, which I originally defined inside the utilities module and which is the cursor object from the MySQLdb module. Later, I realized that the cursor object (which is used to communicate with the db server) must be defined in the main module , so that the main module and everything that is imported into it can access this object.

The end result will 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 utility functions, it causes the aforementioned error "global name not defined".

A special assumption was that the expression “from the import cur program” was specified in the utilities file, for example:

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 this cyclic import or something like that, and on the bottom line it also fails. So my question is:

How can I make the "cur" object defined in the main module visible to those helper functions that are imported into it?

Thank you for your time and my deepest apologies if the decision was published elsewhere. I just can't find the answer myself, and I no longer have tricks in my book.

+73
python namespaces mysql-python python-import
Apr 11 '13 at 21:53
source share
8 answers

Globals in Python are global for a module, not all modules. (Many people are confused by this, because, for example, in C, the global implementation is the same for all implementation files, unless you explicitly make it static .)

There are various ways to solve this problem, depending on your actual use.




Before you take this path, ask yourself if it really should be global. Maybe you really need a class with f as an instance method, and not just a free function? Then you can do something like this:

 import module1 thingy1 = module1.Thingy(a=3) thingy1.f() 



If you really want a global one, but it just needs to be used by module1 , install it in this module.

 import module1 module1.a=3 module1.f() 



On the other hand, if a is shared by many modules, put it in a different place and each one imports 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 

Do not use from imports if the variable is not a constant. from shared_stuff import a will create a new variable a initialized by any shared_stuff.a mentioned during import, and this new variable a will not depend on the purpose of shared_stuff.a .




Or, in the rare case when you really need it to be truly global everywhere, like built-in, add it to the built-in module. The exact details differ between Python 2.x and 3.x. In 3.x, it works as follows:

 import builtins import module1 builtins.a = 3 module1.f() 
+178
Apr 11 '13 at 22:00
source share

As a workaround, you might consider setting environment variables in the outer layer, for example.

main.py:

 import os os.environ['MYVAL'] = str(myintvariable) 

mymodule.py:

 import os print os.environ['MYVAL'] 

As an extra precaution, handle the case where MYVAL is not defined inside the module.

+5
Mar 30 '16 at 8:02
source share

The function uses the global values ​​of the module in which it is defined. Instead of setting a = 3 , for example, you should set module1.a = 3 . So, if you want cur be accessible as global in utilities_module , set utilities_module.cur .

Best solution: do not use global variables. Pass the variables you need to the functions you need or create a class to combine all the data together and pass it when you initialize the instance.

+3
Apr 11
source share

This post is just an observation of the Python behavior I came across. Perhaps the tips you read above do not work for you if you did the same thing as I did below.

Namely, I have a module that contains global / common variables (as indicated above):

 #sharedstuff.py globaltimes_randomnode=[] globalist_randomnode=[] 

Then I had a main module that imports the general stuff with:

 import sharedstuff as shared 

and some other modules that actually populated these arrays. They are called by the main module. When exiting these other modules, I can clearly see that the arrays are full. But, reading them in the main module, they were empty. That was pretty weird for me (well, I'm new to Python). However, when I change the import method of sharestuff.py in the main module, do the following:

 from globals import * 

it worked (arrays were full).

Just say

+3
Apr 17 '15 at 13:38 on
source share

The simplest solution to this problem would be to add another function in the module that would keep the cursor in the global variable for the module. Then all other functions could also use it.

module1:

 cursor = None def setCursor(cur): global cursor cursor = cur def method(some, args): global cursor do_stuff(cursor, some, args) 

The main program:

 import module1 cursor = get_a_cursor() module1.setCursor(cursor) module1.method() 
+2
Aug 14 '15 at 14:16
source share

Since global variables 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 global for these
  • Migrate global global core modules.

addglobals = lambda x: globals (). update (x)

Then you need to pass the current global values:

import module

module.addglobals (globals ())

+1
Nov 30 '15 at 14:34
source share

Since I did not see this in the answers above, I decided to add my simple workaround, which is to add the global_dict argument to the function that requires the global variables of the calling module, and then pass the dict to the function when called; eg:

 # 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 
0
Oct 15 '18 at 16:16
source share

An OOP way to do this is to make your module a class instead of a collection of unrelated methods. Then you can use __init__ or the setter method to set variables from the caller for use in module methods.

0
Apr 12 '19 at 18:26
source share



All Articles