Python: reload component Y imported with 'from X import Y'?

Answer

From my tests, the marked answer, which suggests a simple reload(X), does not work.

From what I can tell the correct answer is:

from importlib import reload # python 2.7 does not require this
import X
reload( X )
from X import Y

Test

My test was the following (Python 2.6.5 + bpython 0.9.5.2)

X.py:

def Y():
    print "Test 1"

bpython:

>>> from X import Y
>>> print Y()
Test 1
>>> # Edit X.py to say "Test 2"
>>> print Y()
Test 1
>>> reload( X )  # doesn't work because X not imported yet
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'X' is not defined
>>> import X
>>> print Y()
Test 1
>>> print X.Y()
Test 1
>>> reload( X ) # No effect on previous "from" statements
>>> print Y()
Test 1
>>> print X.Y() # first one that indicates refresh
Test 2
>>> from X import Y
>>> print Y()
Test 2 
>>> # Finally get what we were after

If Y is a module (and X a package) reload(Y) will be fine -- otherwise, you'll see why good Python style guides (such as my employer's) say to never import anything except a module (this is one out of many great reasons -- yet people still keep importing functions and classes directly, no matter how much I explain that it's not a good idea;-).


from modulename import func

import importlib, sys
importlib.reload(sys.modules['modulename'])
from modulename import func

First off, you shouldn't be using reload at all, if you can avoid it. But let's assume you have your reasons (i.e. debugging inside IDLE).

Reloading the library won't get the names back into the module's namespace. To do this, just reassign the variables:

f = open('zoo.py', 'w')
f.write("snakes = ['viper','anaconda']\n")
f.close()

from zoo import snakes
print snakes

f = open('zoo.py', 'w')
f.write("snakes = ['black-adder','boa constrictor']\n")
f.close()

import zoo
reload(zoo)
snakes = zoo.snakes # the variable 'snakes' is now reloaded

print snakes

You could do this a few other ways. You could automate the process by searching through the local namespace, and reassigning anything that was from the module in question, but I think we are being evil enough.