5

As per this Question's accepted answer, I understand I cannot create pure global variables. Okay, cool.

However, he then goes on and says:

[..]all you can do is make a variable in a particular scope. (If you make a variable inside the Python interpreter, and then import other modules, your variable is in the outermost scope and thus global within your Python session.[..]

Okay, so we can't assign globals in the original sense, but it appears to be possible to access variables in the outermost scope from within a package, via the global keyword, correct?

I am then, apparently, missing something crucial in my efforts to access a variable passed to my python program via commandline arguments.

My program has the usual __main__.py, which handles argument parsing and executes code from my python module backend.

backend has code that relies on input via command line arguments. However, I seem to fail at making these arguments available to backend.

My package's layout is:

mypackage
- __main__.py
- backend/
    -__init__.py
    -direction.py

Here's __main__.py:

import argparse

# Setup ArgParser
parser = argparse.ArgumentParser(description="Fancy Description of program.")
parser.add_argument('--tar', nargs=1, dest='target',
                help='Specify output folder.',
                default=['/path/to/output'])

target_dir = args.target[0]

# Import backend now that our variable is set.
from backend.direction import direction

And my backend/direction.py:

global target_dir
print(target_dir)

Running this raises a NameError: 'target_dir' is not defined. So where's the poop ? Am I assuming an impossibility here, or am I simply messing up on declaration?

Community
  • 1
  • 1
deepbrook
  • 2,076
  • 1
  • 23
  • 38
  • When we say `global`, it means that the variable is defined somewhere in the outer scope. It will not be visible to other modules. (Every file you create is a module, in Python). So, you need to explicitly `import` the module to access the variable. – thefourtheye Jun 10 '16 at 08:47
  • So, in my case I import `__main__` in my `direction.py` ? That doesn't sound pretty, nor like something that should be done(?). Is it acceptable to load variable from a file as a workaround, instead? – deepbrook Jun 10 '16 at 08:53
  • @j4ck Truthfully, you probably shouldn't be using global variables at all. If you do have to use them, generally best to keep them constrained to a single module (see [PEP8](https://www.python.org/dev/peps/pep-0008/#global-variable-names)). – Brendan Abel Jun 10 '16 at 08:54
  • 1
    I'm not sure why you want to use globals here at all, to be honest. You should be passing `target_dir` into whatever functions actually need it. If there are many, consider using a class. – Daniel Roseman Jun 10 '16 at 09:03
  • I guess I was simply hung up on the `global` keyword, somehow. `target_dir` is passed to almost all my functions, so I suppose I wanted to work around having to type it for each call - but I see how the suggestions and answers here make it clear why `global` is nonesense for this undertaking. – deepbrook Jun 10 '16 at 09:15

2 Answers2

13

global only works within the module it's used in. You also don't use global to declare a global variable at the global scope (ie. the module scope). You would use global within the scope of a function to indicate that you want to use a variable in the global scope and not in the local scope.

In python 3, there is also the nonlocal keyword that allows you to indicate you want to modify a variable in an outer scope that isn't the global/module scope.

global

A = 1

def global_func():
    global A
    A = 2


def func():
    A = 3


print(A)
# 1

global_func()
print(A)
# 2

func()
print(A)
# 2

nonlocal

def outside():
    a = 1

    def inside_nonlocal():
        nonlocal a
        a = 2

    def inside():
        a = 3

    print(a)
    # 1

    inside_nonlocal()
    print(a)
    # 2

    inside()
    print(a)
    # 2
Brendan Abel
  • 28,703
  • 11
  • 72
  • 95
0

I am not clear what your problem actually is. Is it not possible to do the following?

import backend

if __name__ == "__main__":
    # parse arguments
    backend.argreceive(arguments)

As Daniel Roseman suggested, if there are many backend functions requiring access to these variables then you should consider using a class, and class properties, to store the variables.

class argreceive():
    def __init__(self,args):
        self.args = args
dodell
  • 464
  • 3
  • 7