代码之家  ›  专栏  ›  技术社区  ›  ely

应导入lib。在Python 3.6中重新加载还原已删除的属性?

  •  5
  • ely  · 技术社区  · 6 年前

    我正在研究这两个相关的问题: here here .

    我在Python 3.6中看到了一个我不期望的行为,这与使用plain的行为不同 reload 在Python 2.7(和3.4)中。也就是说,似乎在模块初始化期间或在重新加载期间重新执行模块时填充的模块属性在使用删除其本地名称后不会恢复 del ... 见下文:

    对于Python 3.6:

    In [1]: import importlib
    
    In [2]: import math
    
    In [3]: del math.cos
    
    In [4]: math.cos
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-4-05b06e378197> in <module>()
    ----> 1 math.cos
    
    AttributeError: module 'math' has no attribute 'cos'
    
    In [5]: math = importlib.reload(math)
    
    In [6]: math.cos
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-6-05b06e378197> in <module>()
    ----> 1 math.cos
    
    AttributeError: module 'math' has no attribute 'cos'
    
    In [7]: importlib.reload(math)
    Out[7]: <module 'math' from '/home/ely/anaconda/envs/py36-keras/lib/python3.6/lib-dynload/math.cpython-36m-x86_64-linux-gnu.so'>
    
    In [8]: math.cos
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-8-05b06e378197> in <module>()
    ----> 1 math.cos
    
    AttributeError: module 'math' has no attribute 'cos'
    

    对于Python 2.7(和 Python 3.4 ):

    In [1]: import math
    
    In [2]: del math.cos
    
    In [3]: math.cos
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-3-05b06e378197> in <module>()
    ----> 1 math.cos
    
    AttributeError: 'module' object has no attribute 'cos'
    
    In [4]: reload(math)
    Out[4]: <module 'math' from '/home/ely/anaconda/lib/python2.7/lib-dynload/math.so'>
    
    In [5]: math.cos
    Out[5]: <function math.cos>
    

    我试着从 source code 一直到 C-level module exec function ,我看不到任何逻辑会导致它无法写入重新初始化的 cos 属性返回到模块的模块作用域全局的dict中。

    我怀疑这是C级重新执行逻辑中的某种类型的错误,它查看模块字典中找到的属性名称(以前导入时就存在的名称,可能会经过变异删除属性,如我的示例所示),然后使用 exec 要将模块的执行副作用写入该字典,需要跳过键名(如 余弦 )这与Python 2.7的行为不同,在模块的名称空间中不存在。

    1 回复  |  直到 6 年前
        1
  •  3
  •   Community THelper    4 年前

    我相信这是(有意的?无意的?)的影响 PEP 489 ,是对扩展模块初始化的一次大修。政治公众人物包括以下部分:

    模块重新加载

    使用importlib重新加载扩展模块。重载()将继续无效,除非重新设置 导入相关属性。

    由于共享库加载的限制(POSIX上的dlopen和 通常无法加载 在磁盘上更改库后对其进行了修改。

    用于重新加载而不是尝试新版本的 模块太少,无法要求所有模块作者继续重新加载 介意如果需要类似重载的功能,作者可以导出 专用功能。

    这个 code change 在实现PEP 489的提交中引入了似乎对这种行为负责的。

    即使是Python 3.4也不支持从更改的文件中重新加载扩展模块;最接近的是代码 save a copy 初始化后模块dict的 copy the contents 重新加载时返回模块的实际dict。该代码 still exists ,但它不再在重新加载时触发,我不知道它是否打算在重新加载时触发。我相信代码目前只用于子口译员。