在交互式上删除了模块的功能。如何重新导入? importlib.reload没有帮助

时间:2018-02-15 13:28:42

标签: python python-3.x ipython python-importlib

我在ipython上删除了(package builtin)函数:

Python 3.6.4 |Anaconda custom (64-bit)| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import math

In [2]: math.cos(0)
Out[2]: 1.0

In [3]: del math.cos

In [4]: math.cos(0)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-9cdcc157d079> in <module>()
----> 1 math.cos(0)

AttributeError: module 'math' has no attribute 'cos'

行。但是如何重新加载该功能呢?这没有帮助:

In [5]: import importlib

In [6]: importlib.reload(math)
Out[6]: <module 'math' (built-in)>

In [7]: math.cos(0)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-7-9cdcc157d079> in <module>()
----> 1 math.cos(0)

AttributeError: module 'math' has no attribute 'cos'

2 个答案:

答案 0 :(得分:3)

以上代码适用于Windows上的Python 3.4,但适用于3.6状态的documentation

  

请注意,好像您保留对模块对象的引用,使其在sys.modules中的缓存条目无效,然后重新导入命名模块,两个模块对象将不同。相比之下,importlib.reload()将重用相同的模块对象,只需重新运行模块的代码即可重新初始化模块内容。

(也许我只是“幸运”)

所以非常有效的是:

import math,sys
del math.cos
del math
sys.modules.pop("math")   # remove from loaded modules
import math
print(math.cos(0))

它仍然有效,你甚至不需要reload。只需从缓存中移除&amp;再次进口。

正如评论中所述,使用reload也可以,但是您需要更新reload给出的模块引用,而不仅仅重用缺少cos条目的旧版本:

import math,sys
del math.cos
import importlib
math = importlib.reload(math)
print(math.cos(0))

答案 1 :(得分:0)

好的人,我写了一个小模块来解决这个困惑。 我真诚地怀疑它是无懈可击的。所以欢迎改进。

这个模块在Py 2和3上运行良好。试用Python 2.7和Python 3.5。



# rld.py --> the reloading module

import sys

__all__ = ["reload"]

try:
    # Python 2:
    _reload = reload
    from thread import get_ident
    def reload (module):
        if isinstance(module, basestring):
            module = sys.modules[module]
        if module.__name__==__name__:
            raise RuntimeError("Reloading the reloading module is not supported!")
        print ("Reloading: %s" % module.__name__)
        # Get locals() of a frame that called us:
        ls = sys._current_frames()[get_ident()].f_back.f_locals
        # Find variables holding the module:
        vars = [name for name, mod in ls.iteritems() if mod==module]
        if len(vars)==0:
            print ("Warning: Module '%s' has no references in this scope.\nReload will be attempted anyway." % module.__name__)
        else:
            print("Module is referenced as: %s" % repr(vars))
        # Reload:
        m = _reload(module)
        for x in vars:
            ls[x] = m
        print("Reloaded!")
except NameError:
    # Python 3:
    from _thread import get_ident
    def reload (module):
        if isinstance(module, str):
            module = sys.modules[module]
        if module.__name__==__name__:
            raise RuntimeError("Reloading the reloading module is not supported!")
        print ("Reloading: %s" % module.__name__)
        # Get locals() of a frame that called us:
        ls = sys._current_frames()[get_ident()].f_back.f_locals
        # Find variables holding the module:
        vars = [name for name, mod in ls.items() if mod==module]
        if len(vars)==0:
            print ("Warning: Module '%s' has no references in this scope.\nReload will be attempted anyway." % module.__name__)
        else:
            print("Module is referenced as: %s" % repr(vars))
        # Dereference all detected:
        for x in vars:
            del ls[x]
        del sys.modules[module.__name__]
        # Reimport:
        m = __import__(module.__name__)
        # Rebind to old variables:
        for x in vars:
            ls[x] = m
        # Remap references in the old module
        # to redirect all other modules that already imported that module:
        for vname in dir(m):
            setattr(module, vname, getattr(m, vname))
        print("Reloaded!")

>>> # Usage:
>>> from rld import * # Always import it first - just in case
>>> import math
>>> math.cos
<built-in function cos>
>>> del math.cos
>>> math.cos
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'cos'
>>> reload(math)
Reloading: math
Module is referenced as: ['math']
Reloaded!
>>> math.cos
<built-in function cos>
>>> #-------------------------
>>> # This also works:
>>> import math as quiqui
>>> alias = quiqui
>>> del quiqui.cos
>>> quiqui.cos
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'cos'
>>> alias.cos
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'cos'
>>> reload("math")
Reloading: math
Module is referenced as: ['alias', 'quiqui']
>>> quiqui.cos
<built-in function cos>
>>> alias.cos
<built-in function cos>