1

Beginner here. I'm trying to learn about global/local variables, circular imports, and how to avoid them. I have three files:

#globaltest
import pandas as pd

x = 0
dic = {'1995': [3,5,2,1,2,7],
         '1996': [6,3,1,1,1,8],
      }
df = pd.DataFrame(dic, columns = ['1995','1996'], index=['AT1','AT2','AT3','FR1','FR5','FR7'])
df.index.name='Geo'

Second file is:

  #prueba
    from globaltest import x,df
    
    def abcde():
        #from globaltest import x,df
        while x<5:
            print("Not yet")
            x=x+1
        print("Now ",df)

And the third file is:

#main
from prueba import abcde

ab=int(input("Option: "))

if ab==1: 
 abcde()

The code works well if in the second file, "prueba", I import the variables from "globaltest" inside of the function abcde(). If I import the variables at the top, however, it doesn't work (UnboundLocalError: local variable 'x' referenced before assignment). I've read that you should not import anything inside functions, so I would like to know what would be the solution to avoid doing it in this case. Thanks in advance!

3
  • do you know what the error you're getting means? Commented Nov 25, 2020 at 9:28
  • @ombk,I think it means the function is trying to use a variable that hasn't been assigned. As I said, if I import the variables from the first program inside the function, the program works. If the import takes place outside, I get the error. I'm trying to understand how it works. Commented Nov 25, 2020 at 9:32
  • You get yourself 2 answers, however, I suggest as a first step to check the definition of global scope variables and local scope variables. This way you will understand why it works in prueba if it is inside and not outside. Commented Nov 25, 2020 at 9:40

2 Answers 2

1

From the docs (emphasis mine):

If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound. This rule is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations.

The name binding happens here: x=x+1.

To simplify your issue, we can use the follwing code, as importing the variables in this case is the same as simply having them in the global scope:

x = 0; df = None

def abcde():
    while x<5:
        print("Not yet")
        x=x+1 # <- this is where the name binding happens, turning x into a local variable
    print("Now", df)

abcde()

Running this code will yield the following error:

UnboundLocalError: local variable 'x' referenced before assignment

To overcome this issue, you should tell python that you want to access the global variable instead of a local reference by sing the global keyword:

x = 0; df = None

def abcde():
    global x
    while x<5:
        print("Not yet")
        x=x+1
    print("Now", df)

abcde()

Output:

Not yet
Not yet
Not yet
Not yet
Not yet
Now None

However, note hat this will only modify x in the global scope of the current module. It will not affect x in the globaltest module, because it's encapsulated in it's own (module) namespace.

To use the very same x, you should reference it with module.variable:

import globaltest

def abcde():
    while globaltest.x < 5:
        print("Not yet")
        globaltest.x += 1
    print("Now", globaltest.df)

abcde()

If you access the variable via module.variable you do not have to use the global keyword.

Sign up to request clarification or add additional context in comments.

Comments

1

You should do the following changes

  #prueba
    import globaltest
    
    def abcde():
        #from globaltest import x,df
        while globaltest.x<5:
            print("Not yet")
            globaltest.x=globaltest.x+1
        print("Now ",globaltest.df)

Here we define that the x we are referring is from globaltest module.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.