删除了模块的交互功能。如何重新导入?importlib.reload导入帮不上忙

2024-04-26 17:20:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我删除了ipython上的(包内置)函数:

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'

好吧。但是如何重新加载函数呢?这没用:

^{pr2}$

Tags: 函数indefaultfortypeipythoncustombit
2条回答

好吧,各位,我写了一个小模块来解决这个困惑。 我真诚地怀疑这是没有错误的。因此,改进是受欢迎的。在

这个模块在py2和py3上都能很好地工作。尝试了Python2.7和Python3.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>

上面的代码适用于Windows上的Python3.4,但3.6的documentation是这样的:

Beware though, as if you keep a reference to the module object, invalidate its cache entry in sys.modules, and then re-import the named module, the two module objects will not be the same. By contrast, importlib.reload() will reuse the same module object, and simply reinitialise the module contents by rerunning the module’s code.

(所以也许我只是“幸运”)

所以可以肯定的是:

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

你甚至不需要它。只需从缓存中删除并再次导入。在

如注释中所述,使用reload也可以,但是您需要更新reload给出的模块引用,而不仅仅是重用丢失了cos项的同一旧引用:

^{pr2}$

相关问题 更多 >