如何重新加载使用`从模块导入'导入的python模块*`

如何重新加载使用`从模块导入'导入的python模块*`,python,python-import,python-module,Python,Python Import,Python Module,我看到可以使用reload(无论什么模块)或者在Python3中,imp.reload(无论什么模块) 我的问题是,如果我说从任何模块导入*到导入,会怎么样?当我使用reload()时,我没有任何模块可供参考。你们会因为我把整个模块扔进全局名称空间而对我大喊大叫吗?:) 切勿使用导入*;它破坏了可读性 另外,请注意,重新加载模块几乎没有任何用处。您无法预测在重新加载模块后程序将处于何种状态,因此这是一种获得无法理解、无法产生的bug的好方法。a from module import * 从模块

我看到可以使用
reload(无论什么模块)
或者在Python3中,
imp.reload(无论什么模块)


我的问题是,如果我说从任何模块导入*到导入,会怎么样?当我使用
reload()
时,我没有
任何模块
可供参考。你们会因为我把整个模块扔进全局名称空间而对我大喊大叫吗?:)

切勿使用
导入*
;它破坏了可读性

另外,请注意,重新加载模块几乎没有任何用处。您无法预测在重新加载模块后程序将处于何种状态,因此这是一种获得无法理解、无法产生的bug的好方法。

a

from module import *
模块
获取所有“导出”对象,并将它们绑定到模块级别(或您的作用域级别)名称。您可以按以下方式重新加载模块:

reload(sys.modules['module'])
但这对你没有任何好处:不管你的作用域是什么,级别名称仍然指向旧对象。

我同意“一般不要这样做”的共识,但是

正确答案是:

import X
reload(X)
from X import Y  # or * for that matter

当使用
从which_模块导入which
时,
which
被视为导入模块的一部分,因此要重新加载它,您应该重新加载模块。但只要重新加载模块,您仍然会从已导入的
whatever\u模块中获得旧的
whatever
,因此您需要重新加载(whatever\u模块),然后重新加载模块:

# reload(whatever_module), if you imported it
reload(sys.modules['whatever_module'])
reload(sys.modules[__name__])
如果您使用了来自which_模块的
导入which
,您也可以考虑

whatever=reload(sys.modules['whatever_module']).whatever


更清晰的答案是Catskul的好答案和Ohad Cohen对系统模块的使用以及直接重新定义的混合:

import sys
Y = reload(sys.module["X"]).Y  # reload() returns the new module
实际上,执行
import X
会创建一个新符号(
X
),该符号可能会在随后的代码中重新定义,这是不必要的(而
sys
是一个通用模块,因此不应发生这种情况)

这里有趣的一点是,
from X import Y
不会将
X
添加到名称空间中,而是将模块
X
添加到已知模块的列表中(
sys.modules
),这允许重新加载模块(并访问其新内容)

更一般地说,如果需要更新多个导入的符号,则按如下方式导入它们会更方便:

import sys
reload(sys.module["X"])  # No X symbol created!
from X import Y, Z, T
对于python 3.7:

from importlib import reload #import function "reload"
import YourModule #import your any modules
reload(YourModule) #reload your module
可以从您自己的函数调用重载函数

def yourFunc():
   reload(YourModule)

我找到了另一种在导入时重新加载模块的方法,如:

from directory.module import my_func
很高兴知道模块通常是如何导入的。 在
sys.modules
字典中搜索模块。如果它已存在于sys.modules中,则不会再次导入该模块

因此,如果我们想重新加载模块,我们可以将其从sys.modules中删除,然后再次导入:

import sys
from directory.module import my_func
my_func('spam')
# output: 'spam'

# here I have edited my_func in module.py

my_func('spam') # same result as above
#output: 'spam'


del sys.modules[my_func.__module__]
from directory.module import my_func

my_func('spam') # new result
#output: 'spam spam spam spam spam'
如果您想在运行整个脚本时重新加载模块,可以使用异常处理程序:

try:
    del sys.modules[my_func.__module__]

except NameError as e:
    print("""Can't remove module that haven't been imported.
    Error: {}""".format(e))

from utils.module import my_func

..........
# code of the script here

关于你的最后一个问题:是的。(1)考虑到这个问题是在4月1日提出的(即使是两年前),我本希望答案能更幽默一些。(2) Python教程说:“但是,[从模块导入*]可以在交互会话中保存键入;在我看来,这正是需要重新加载的情况(您刚刚修复了正在交互测试的函数中的错误,并且不希望离开解释器来保存其他测试数据)(3)Catskul确实为提出的问题提供了唯一正确的答案;请接受并投票!Catskul的答案很好,但不是“唯一正确”的答案:它不必要地创建了一个新符号
X
,而该符号通常不在原始代码中(如何避免这种副作用,请参见Ohad Cohen或我的答案)。这在交互模式下很有用,但我总是更新我的模块,然后必须跳出并返回python。这也是为什么我使用import*from\uuuuuuuuuu,这只是为了交互模式,所以我不必键入太多内容。如果您使用
python-i foo.py
,您可以让python在给出提示之前运行所有安装代码。(与其使用somepackage.foo import*
中的
,不如使用somepackage import foo中的
作为f
,然后参考
f.yourObjects
,等等?啊,但我仍然无法从somepackage import*中执行任何操作(至少在我的python 3中)…我知道你们中没有人希望我能够执行此操作!;)@Jaretholt,您现在可能已经明白了这一点,但是只需执行
reload(mod)
这通常会将符号
X
添加到名称空间中,因此通过执行
reload(sys.modules[“X”])来尊重不在名称空间中的
X
会更干净一些
。当然,这可能需要将
sys
添加到名称空间中,但这是一个非常常见的模块,因此不应该对任何内容进行阴影处理(而
X
可能会被添加的
import X
阴影处理)。如果导入带有别名的模块,请使用
重新加载
中的别名。例如,对于
导入XX as X
使用
重新加载(X)
,当我从包的模块导入对象时(
从包导入。模块导入对象
)。此评论不回答原始问题。很好!我喜欢此解决方案。谢谢分享!
import sys
from directory.module import my_func
my_func('spam')
# output: 'spam'

# here I have edited my_func in module.py

my_func('spam') # same result as above
#output: 'spam'


del sys.modules[my_func.__module__]
from directory.module import my_func

my_func('spam') # new result
#output: 'spam spam spam spam spam'
try:
    del sys.modules[my_func.__module__]

except NameError as e:
    print("""Can't remove module that haven't been imported.
    Error: {}""".format(e))

from utils.module import my_func

..........
# code of the script here