Search code examples
pythonpython-module

How to explain using "from X import Y" to import a function Y which in uses a variable in the X file?


I know that the reload() function can't affect the from <module> import <name>" which were used before thereload()`, but I tested it and found something odd:

test1.py:

message="before editing"
def printer():
    print("reload",message)

test1.py (changed):

message="after editing"
def printer():
    print("reload",message)

then I used the interpreter and entered:

from test1 import printer
printer()
import test1
test1.printer()

#change the test1.py
reload(test1)
test1.printer()
printer()

after reload,the result is:

>>> test1.printer()
('reload:', 'after editing')
>>> printer()
('reload:', 'after editing')

So, why does printer() see the change? I thought the reason may be variable binding.


Solution

  • Reloading updates the existing module. Functions from a module contain a reference to the module globals:

    >>> printer.__globals__ is test1.__dict__
    True
    >>> 'message' in printer.__globals__
    True
    >>> printer.__globals__['message'] is test1.message
    True
    

    It is through this reference that globals like message are resolved. Because reload() function updates the existing module namespace, the printer function object will use the new value.

    The problem with reload() and imported names from a module (rather than a reference to the module itself) is that those references are not updated. If you had changed the definition of the printer() function itself rather than the message global, then the imported reference to that function would not have changed.

    Quoting from the reload() function documentation:

    When a module is reloaded, its dictionary (containing the module’s global variables) is retained. Redefinitions of names will override the old definitions, so this is generally not a problem.

    Emphasis mine.