jcomeau_ictx
jcomeau_ictx

Reputation: 38492

How to assign a value to an imported global?

After all these years, I still don't grok globals in Python. My problem is showing up in a uWSGI app, where in init() I'm setting BROWSER = webdriver.Firefox() after declaring global BROWSER, and it's not actually setting the variable. But I'm also seeing it at the Python command line, and hopefully if I can understand why this simple example isn't working, it will solve my uWSGI issues as well.

globaltest.py:

#!/usr/bin/python3
'''
Test of keyword `global`
'''
GLOBALTEST = None

def init():
    global GLOBALTEST
    GLOBALTEST = 'Something'

if __name__ == '__main__':
    print('before init: GLOBALTEST', GLOBALTEST)
    init()
    print(' after init: GLOBALTEST', GLOBALTEST)

Execution:

jcomeau@bendergift:/tmp$ ./globaltest.py 
before init: GLOBALTEST None
 after init: GLOBALTEST Something
jcomeau@bendergift:/tmp$ python3
Python 3.7.3 (default, Apr  3 2019, 05:39:12) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from globaltest import *
>>> GLOBALTEST
>>> init()
>>> GLOBALTEST
>>> 

Upvotes: 1

Views: 69

Answers (2)

chepner
chepner

Reputation: 532238

The main thing to remember is that Python has only one scope that is truly global: the built-in scope. The "global" scope is really a module global scope, and there is one for each module in the program.

There are two global variables named GLOBALTEST in your interactive session. One is part of the global scope of the module globaltest; the other is part of the global scope of your interactive session, the module __main__.

init sets the value of globaltest.GLOBALTEST, because Python uses lexical scoping. You are checking the value of __main__.GLOBALTEST before and after calling init.

If you check the value of globaltest.GLOBALTEST, you'll see its value change:

>>> from globaltest import *
>>> import globaltest
>>> globaltest.GLOBALTEST
>>> init()
>>> globaltest.GLOBALTEST
'Something'
>>> GLOBALTEST
>>>

Upvotes: 2

jcomeau_ictx
jcomeau_ictx

Reputation: 38492

Based on chepner's answer, I was able to partially solve my uwsgi problem with the following kludge:

if not APP in sys.modules:  # will be the case with uwsgi
    exec('import %s' % APP)
sys.modules[APP].BROWSER = webdriver.Firefox()

However, the thread I'm running in the background still doesn't work correctly, as it did before I tried to move the webdriver initialization into a subroutine. So I'm back to initializing it in my if __name__ == '__main__' and else blocks.

Upvotes: 0

Related Questions