12

How can I use external variables in Python, like extern int x; in C?

For example,

main1.py:

from myfunc import print_a 

a = 10 
print a    
print_a()

myfunc.py:

def print_a():
    global a   
    print a
Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
Je-Hoon Song
  • 301
  • 1
  • 4
  • 7

3 Answers3

11

Simply re-assign the variable in the module:

import myfunc
from myfunc import print_a 

a = 10 

print a

myfunc.a = a

print_a()

Otherwise it is not possible.

Rememeber that python treats modules in a way that is quite different from C. The import in python does not "copy the contents" of the file in that place, but it executes the code in the given file and creates a module object.

The global variable of the module are the module object attributes, which can be modified as I've shown. There is no such notion as "global variable" except for built-ins.


I'd suggest to refactor your code in such a way that you don't have to modify this global variable at all, moving the code that uses myfunc.a from main1 to myfunc. The fact that you need such global variable is already a code smell that there's something wrong with your code and you should try to fix it.


Actually there is a way to affect the "global scope" but it is so hackish that I don't even want to mention it. Trust me: you don't want to use it. If people see your code using such a hack you may be in physical danger.

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
  • But OP wants to use the same `a` variable from `main1`, not just see a copy of it – Ryan Haining Aug 03 '13 at 16:29
  • @RyanHaining Where do you see a "copy"? In my example I simply add/change a *reference*, which doesn't imply copying anything so changes to the variable in a module are seen in the other module asweel, except when the object is immutable(in which case you shouldn't care for identity anyway). – Bakuriu Aug 03 '13 at 16:44
  • you're copying the reference to an immutable type here to `myfunc`. If the value of `a` changes in `main1` this won't be reflected in `myfunc.a` unless you manually change it there as well each time you change it in `main1`. – Ryan Haining Aug 03 '13 at 17:01
  • even if it's mutable, reassigning to `a` won't change what it is in `myfunc.a`. This behavior is wildly different from the `extern`-like behavior OP is asking for. – Ryan Haining Aug 03 '13 at 17:03
  • @RyanHaining The point of my answer is exactly this: you cannot do so that when you do `a = something` in a module the value changes in the other, hence **you must manually reassign the value to every module every time you want to reassign that variable**. As I said in my answer there is a way to achieve "exactly" the behaviour the OP wants(with a slightly different syntax), but I'm not going to put it here since it could lead people reading the answer to use it, which is something *nobody* wants. – Bakuriu Aug 03 '13 at 18:09
  • I don't see this as something anybody would want either. Having a module depend on another module to set its globals? However, I think the OP's intention is to access another modules global variables, or share globals across modules. – Ryan Haining Aug 04 '13 at 01:50
3

Unlike C, variables declared at global scope are still limited in scope to the module they are created in, so you need to qualify the name a with the module it lives in.

The global keyword is used when you are going to modify a global variable by reassigning, you do not need it when you are just referencing a global variable.

If you are trying to access a variable of another file, you must import that module, and because of the way your files are structured you have a couple of ways to resolve issues:

Option 1) Move the referencing of myfunc.print_a inside of a function and import main1 inside myfunc to see a

main1.py

import myfunc

a = 10 

def main():
    print a    
    myfunc.print_a()

if __name__ == '__main__':
    main()

myfunc.py

import main1

def print_a():
    print main1.a

Option 2) recommended Move the variable(s) into another module and have both myfunc and main1 import it.

vals.py

a = 20

main1.py

import vals
from myfunc import print_a

vals.a = 10 

print vals.a    
print_a()

myfunc.py

import vals

def print_a():
    print vals.a
Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
-1

This is a workaround to this problem by using a common external file. In this example I am storing an index variable to flag in each application whether a file is being accessed. The variable indxOpen in ext1.py and indxO in ext2.py are being updated and stored in a common external text file "externalVars.txt"

lead application ext1.py

# lead application ext1.py 
 #this alternately flips the value of indxOpen on prime number intervals 
 import time

 def update(d,v1):
      f=open(d+'externalVars.txt','r+')
      f.write(str( v1)) 
      f.truncate()
      f.close()

 # ensure variable is initialised and made available to external apps
 indxOpen = False
 var_dir = "<your external var directory>/"
 try:
      f =open(var_dir+'externalVars.txt','r')
 except:
      f= open(var_dir+'externalVars.txt','w')
      f.close()
 # this alternately flips the value of indxOpen on prime number intervals    
 update(var_dir,indxOpen)
 i = 0
 while True:   
      while indxOpen:
      i += 1
      if (i % 13) ==0:
        indxOpen = indxOpen ^ True
        update(var_dir,indxOpen)
       f=open(var_dir+'externalVars.txt','r+')
       t=f.readline()
       print "app1",t," ",i
       if t=='False':
           print "app1 updated"
           update(var_dir,indxOpen)
           indxOpen = False  
        else:
            time.sleep(1.4)

   while not indxOpen:
       f=open(var_dir+"externalVars.txt","r+")
       t=f.readline()
       print "app1",t
       if t=='True':           
           indxOpen = True          
       else:
           time.sleep(1)

ext2.py following application

#   ext2.py this alternately flips the value of indxO on prime number intervals but it is         initialised by the lead application
# in this case ext1.py
# python 2.7.12
import time

def update(d,v1):
    f=open(d+'externalVars.txt','r+')
    f.write(str( v1))
    f.truncate()
    f.close()

var_dir = "<your external var directory>/"

# intialise external variable
f=open(var_dir+'externalVars.txt','r+')
t=f.readline()
if t=='True':
    indxO= True
if t=='False':
    indxO= False
i=0
while True:

    while indxO:    
        f=open(var_dir+"externalVars.txt","r+")
        t=f.readline()
        print "app2",t
        if t=='False':
            indxO = False       
            update(var_dir,indxO)
        else:
            time.sleep(1.5)


    while not indxO:
        i += 1
        if (i % 17) ==0:
            indxO = indxO ^ True
            update(var_dir,indxO)
        f=open(var_dir+"externalVars.txt","r+")
        t=f.readline()
        print "app2",t," ",i
        if t=='True':
            indxO = True
            print "apt2 updated"
            update(var_dir,indxO)
        else:
            time.sleep(1.3)
pmr
  • 1