简体   繁体   English

如何重新加载使用`from module import *`导入的python模块

[英]How to reload python module imported using `from module import *`

I saw in this useful Q&A that one can use reload(whatever_module) or, in Python 3, imp.reload(whatever_module) .我在这个有用的问答中看到可以使用reload(whatever_module)或者在 Python 3 中imp.reload(whatever_module)

My question is, what if I had said from whatever_module import * to import?我的问题是,如果我说from whatever_module import *到import 会怎样? Then I have no whatever_module to refer to when I use reload() .然后,当我使用reload()时,我没有whatever_module可参考的模块。 Are you guys gonna yell at me for throwing a whole module into the global namespace?你们会因为我把整个模块扔进全局命名空间而对我大喊大叫吗? :) :)

I agree with the "don't do this generally" consensus, but... 我同意“不要这样做”的共识,但......

The correct answer is: 正确答案是:

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

Never use import * ; 切勿使用import * ; it destroys readability. 它破坏了可读性。

Also, be aware that reloading modules is almost never useful. 另外,请注意重新加载模块几乎从不有用。 You can't predict what state your program will end up in after reloading a module, so it's a great way to get incomprehensible, unreproduceable bugs. 你无法预测你的程序在重新加载模块后最终会处于什么状态,所以这是获得难以理解的,无法解决的错误的好方法。

A 一个

from module import *

takes all “exported” objects from module and binds them to module-level (or whatever-your-scope-was-level) names. module获取所有“导出”对象,并将它们绑定到模块级别(或任何您的范围级别)名称。 You can reload the module as: 可以将模块重新加载为:

reload(sys.modules['module'])

but that won't do you any good: the whatever-your-scope-was-level names still point at the old objects. 但这对你没有任何好处:无论你的范围是什么级别的名字仍然指向旧的对象。

A cleaner answer is a mix of Catskul's good answer and Ohad Cohen's use of sys.module and direct redefinition: 一个更清晰的答案是Catskul的好答案和Ohad Cohen使用sys.module和直接重新定义的混合:

import sys
Y = reload(sys.module["X"]).Y  # reload() returns the new module

In fact, doing import X creates a new symbol ( X ) that might be redefined in the code that follows, which is unnecessary (whereas sys is a common module, so this should not happen). 事实上,执行import X会创建一个新的符号( X ),可能会在后面的代码中重新定义,这是不必要的(而sys是一个常见的模块,所以这不应该发生)。

The interesting point here is that from X import Y does not add X to the namespace, but adds module X to the list of known modules ( sys.modules ), which allows the module to be reloaded (and its new contents accessed). 这里有趣的一点是, from X import Y不会将X添加到命名空间,而是将模块X添加到已知模块列表( sys.modules ),这允许重新加载模块(并访问其新内容)。

More generally, if multiple imported symbols need to be updated, it is then more convenient to import them like this: 更一般地说,如果需要更新多个导入的符号,则可以更方便地导入它们,如下所示:

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

I've found another way to deal with reloading a module when importing like:我找到了另一种在导入时处理重新加载模块的方法,例如:

from directory.module import my_func

It's nice to know how do modules are being imported generally.很高兴知道模块是如何被导入的。 The module is searched in sys.modules dictionary.该模块在sys.modules字典中搜索。 If it already exists in sys.modules - the module will not be imported again.如果它已经存在于 sys.modules - 该模块将不会被再次导入。

So if we would like to reload our module, we can just remove it from sys.modules and import again:因此,如果我们想重新加载我们的模块,我们可以将其从 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'

If You would like to get reloaded module when running whole script, you could use exception handler:如果您想在运行整个脚本时重新加载模块,您可以使用异常处理程序:

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

When importing using from whatever_module import whatever , whatever is counted as part of the importing module, so to reload it - you should reload your module. 当使用from whatever_module import whateverwhatever是否计入导入模块的一部分,所以要重新加载它 - 您应该重新加载模块。 But just reloading your module you will still get the old whatever - from the already-imported whatever_module , so you need to reload(whatever_module), and than reload your module: 但就重装你的模块,你仍然会得到老whatever -从已经进口whatever_module ,所以你需要重新加载(whatever_module),比重装你的模块:

# reload(whatever_module), if you imported it
reload(sys.modules['whatever_module'])
reload(sys.modules[__name__])

if you used from whatever_module import whatever you can also consider 如果你使用from whatever_module import whatever你也可以考虑

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

or 要么

whatever=reload(whatever_module).whatever
import re

for mod in sys.modules.values():
    if re.search('name', str(mod)):
        reload(mod)

for python 3.7 : 对于python 3.7:

from importlib import reload #import function "reload"
import YourModule #import your any modules
reload(YourModule) #reload your module

Reload function can be called from your own function 可以从您自己的函数调用重新加载功能

def yourFunc():
   reload(YourModule)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM