Python:重新加载用’from X import Y’导入的组件Y?

2020/12/07 08:11 · python ·  · 0评论

在Python中,一旦我在解释器会话中使用导入了模块X import X,并且模块在外部进行了更改,就可以使用来重新加载该模块reload(X)然后,这些更改将在我的解释器会话中可用。

我想知道当我使用从模块X导入组件Y时是否也可行from X import Y

该语句reload Y不起作用,因为Y本身不是模块,而是模块内部的仅组件(在这种情况下为类)。

是否有可能在不离开解释器会话(或导入整个模块)的情况下重新加载模块的各个组件?

编辑:

为了澄清起见,问题在于模块X导入类或函数Y并在更改时重新加载,而不是从包X重新加载模块Y。

如果Y是一个模块(而X是一个包)reload(Y)就可以了-否则,您将明白为什么优秀的Python样式指南(例如,我的老板的)会说除了模块之外不要导入任何东西(这是许多重要原因之一) -但是人们仍然继续直接导入函数和类,无论我解释多少,这都不是个好主意;-)。

回答

根据我的测试,标记为简单的答案reload(X)是行不通的。

从我可以看出的正确答案是:

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

测试

我的测试如下(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
from modulename import func

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

首先,如果可以避免,则根本不应该使用重装。但是,让我们假设您有自己的理由(即在IDLE中进行调试)。

重新加载库不会使名称重新回到模块的命名空间中。为此,只需重新分配变量:

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

您可以通过其他几种方式执行此操作。您可以通过搜索本地名称空间,然后重新分配所讨论模块中的任何内容来自动化该过程,但是我认为我们已经足够邪恶了。

如果要这样做:

from mymodule import myobject

改为这样做:

import mymodule
myobject=mymodule.myobject

现在,您可以以与计划相同的方式使用myobject(无需到处都是烦人的,难以理解的mymodule引用)。

如果您正在交互工作,并且想要从mymodule重新加载myobject,现在可以使用:

reload(mymodule)
myobject=mymodule.myobject

假设您使用from X import Y,则有两个选择:

reload(sys.modules['X'])
reload(sys.modules[__name__]) # or explicitly name your module

要么

Y=reload(sys.modules['X']).Y

一些注意事项:

A.如果导入范围不在模块范围内(例如,在函数中导入)-您必须使用第二个版本。

B.如果Y是从另一个模块(Z)导入到X中的,则-您必须重新加载Z,而不是重新加载X,然后重新加载模块,即使重新加载所有模块(例如使用[ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ])也可能在重新加载Z之前重新加载X-并且不刷新Y的值。

  1. reload()模块X
  2. reload()Y从中导入模块X

请注意,重新加载不会更改绑定在其他命名空间中的已创建对象(即使您遵循Alex的样式指南)。

如果你在一个jupyter环境中工作,并且已经有from module import function可以使用神奇的功能,autoreload

%load_ext autoreload
%autoreload
from module import function

引进的autoreload在IPython中给出了这里

只是为了跟进AlexMartelliCatskul的回答,reload至少在Python 2中,有些真正简单但令人讨厌的案例似乎令人困惑

假设我有以下源代码树:

- foo
  - __init__.py
  - bar.py

具有以下内容:

init.py:

from bar import Bar, Quux

bar.py:

print "Loading bar"

class Bar(object):
  @property
  def x(self):
     return 42

class Quux(Bar):
  object_count = 0
  def __init__(self):
     self.count = self.object_count
     self.__class__.object_count += 1
  @property
  def x(self):
     return super(Quux,self).x + 1
  def __repr__(self):
     return 'Quux[%d, x=%d]' % (self.count, self.x)

无需使用即可正常工作reload

>>> from foo import Quux
Loading bar
>>> Quux()
Quux[0, x=43]
>>> Quux()
Quux[1, x=43]
>>> Quux()
Quux[2, x=43]

但是尝试重新加载,它要么无效,要么损坏东西:

>>> import foo
Loading bar
>>> from foo import Quux
>>> Quux()
Quux[0, x=43]
>>> Quux()
Quux[1, x=43]
>>> reload(foo)
<module 'foo' from 'foo\__init__.pyc'>
>>> Quux()
Quux[2, x=43]
>>> from foo import Quux
>>> Quux()
Quux[3, x=43]
>>> reload(foo.bar)
Loading bar
<module 'foo.bar' from 'foo\bar.pyc'>
>>> Quux()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "foo\bar.py", line 17, in __repr__
    return 'Quux[%d, x=%d]' % (self.count, self.x)
  File "foo\bar.py", line 15, in x
    return super(Quux,self).x + 1
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> Quux().count
5
>>> Quux().count
6
>>> Quux = foo.bar.Quux
>>> Quux()
Quux[0, x=43]
>>> foo.Quux()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "foo\bar.py", line 17, in __repr__
    return 'Quux[%d, x=%d]' % (self.count, self.x)
  File "foo\bar.py", line 15, in x
    return super(Quux,self).x + 1
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> foo.Quux().count
8

我可以确保bar子模块被重新加载的唯一方法reload(foo.bar)我访问重新加载的Quux的唯一方法是进入并从重新加载的子模块中获取它;foo模块自身保持保持到原来的Quux类对象,大概是因为它使用from bar import Bar, Quux(而不是import bar随后Quux = bar.Quux); 此外,这Quux堂课与自己不同步,这很奇怪。

本文地址:http://python.askforanswer.com/pythonzhongxinjiazaiyongfrom-x-import-ydaorudezujiany.html
文章标签: ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!