'Importing module gives "name not defined" error even though the variable is defined before the import

I have created a very basic script which I saved and can import into Python just fine and I have checked it works, yet I keep coming up with a "name not defined error" even though I have defined the variable before importing it - I have tried global command etc. and nothing.

Seasons.py

if favorite_season == "Winter":
    print("Let it snow!")
>>> favorite_season = "Winter"
>>> import Seasons
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Kaz\documents\Seasons.py", line 1, in <module>
    if favorite_season == "Winter":
NameError: name 'favorite_season' is not defined
>>>


Solution 1:[1]

The imported modules are ran in isolation, without access to externally scoped variables.

If you want to use external variables inside of other modules, best to use functions

Seasons.py

def check(favorite_season):
  if favorite_seaon == "Winter":
     print("Let it snow!")
>>> favorite_season = "Winter"
>>> import Seasons
>>> Seasons.check(favorite_season)
Let it snow!

Solution 2:[2]

The variable needs to be defined in the code that is using the variable (i.e. in your case in the file Seasons.py), not in the code that is importing the module inside which the variable is used.

Solution 3:[3]

In Python, there are scope for the memory.

Here you define favorite_season in the main interactive scope. When you import your module, it has its own scope and your main interactive scope in the console will be able to access this scope. But the opposite is not true.

In particular, we usually don’t expect an imported module to execute code (or very few in some specific case), just propose new methods and classes that you will be able to use.

Solution 4:[4]

Variables belong to the module they are inside of. Unless they are inside of a class or function, then they belong to the class or function they are inside of. Google python scoping for more information on how that works. You can do the following:

Inside main.py:

favorite_season = "Winter"
import Seasons

Inside Seasons.py:

import main

if main.favorite_season == "Winter":
    print("Snuggled Up Warm")
elif main.favorite_season == "Summer":
    print("Yummy Ice Cream")
elif main.favorite_season == "Spring":
    print("Pretty Petals")
else:
    print("Crunchy Bright Leaves")

And then on the terminal you can now run

python3 main.py

Which will correctly output

Snuggled Up Warm

And that will work. However, it's best to create functions instead as modules will only run once, but functions can be used as many times as you want. That would be done like so:

Inside main.py:

import Seasons
Seasons.print_seasonal_message("Winter")

Inside Seasons.py:

def print_seasonal_message(season)
    if season == "Winter":
        print("Snuggled Up Warm")
    elif season == "Summer":
        print("Yummy Ice Cream")
    elif season == "Spring":
        print("Pretty Petals")
    else:
        print("Crunchy Bright Leaves")

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 OneCricketeer
Solution 2
Solution 3 Floh
Solution 4