Scope error working with imported module in Python 3

342 Views Asked by At

I have an imported function from a separate file I have previously created. In it I declare the variable nums to be nonlocal and then work with it. So with that context I will give you a snippet of my code and my error.

cwd = os.getcwd()
sys.path.append(os.path.abspath(cwd + "/myfunctions"))

from opening_questions import opening_questions

def runing_app():

    nums = []

    opening_questions()

    def core_app(jpm):... # this is what I am trying to execute from all this.

    for jpm in nums:
        core_process = multiprocessing.Process(target=core_app, args=(jpm,))
        core_process.start()
        print('RAN')
        break
runing_app()

In opening_questions() I declare nonlocal nums and try to work with nums inside my function. This is the error I get:

Traceback (most recent call last):
File "/home/gdfelt/Python projects/test versions/test(current work)/testX.py", line 22, in <module>
    from opening_questions import opening_questions
File "/home/gdfelt/Python projects/test versions/test(current work)/myfunctions/opening_questions.py", line 19
    nonlocal nums
SyntaxError: no binding for nonlocal 'nums' found 

This code ran just fine before I ran it from a separate file. What do I need to have this code work? I'm using python 3.5 -- if you need clarification, please ask.

1

There are 1 best solutions below

0
On

For me, this comes down to the issue that this works:

def runing_app():
    def opening_questions():
        nonlocal nums
        nums += " World!"

    nums = "Hello"
    opening_questions()
    print(nums)

runing_app()

But this doesn't:

def opening_questions():
    nonlocal nums
    nums += " World!"

def runing_app():
    nums = "Hello"
    opening_questions()
    print(nums)

runing_app()

Regardless of whether we're changing, or just looking at, nums, we get the message:

SyntaxError: no binding for nonlocal 'nums' found"

Which is explained by help('nonlocal'):

Names listed in a "nonlocal" statement, unlike those listed in a "global" statement, must refer to pre-existing bindings in an enclosing scope (the scope in which a new binding should be created cannot be determined unambiguously).

(My emphasis.) In the code that doesn't work, the binding of nums is ambiguous as we don't know who might call opening_questions() at runtime (caller may not define nums). And the binding is not found in the enclosing scope (text).

This would not be the case for global, as no matter who calls opening_questions(), we look in the same place for for a global.

The confusion may come about from dynamic scope languages that first look locally, then up the call stack, and finally globally. In Python there are three non-overlapping options: look locally; look at the enclosing scope; look globally. There's no combining them nor looking up the call stack.