7

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?

5
  • 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. Commented Jun 10, 2016 at 8: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? Commented Jun 10, 2016 at 8: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). Commented Jun 10, 2016 at 8: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. Commented Jun 10, 2016 at 9: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. Commented Jun 10, 2016 at 9:15

2 Answers 2

21

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
Sign up to request clarification or add additional context in comments.

2 Comments

Is there a reason I need to two-line this? global A = 2 could do the job, couldn't it?
@Schnaps No, that's not a valid statement. Those two statements can't be combined.
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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.