【问题标题】:What happens when python's reload() does not find the module file?当 python 的 reload() 找不到模块文件时会发生什么?
【发布时间】:2013-05-07 07:15:25
【问题描述】:

我在运行时为我的应用程序生成代码,因此我需要重新加载我的一些模块以免重新启动。

我生成的包可能包含新文件或已删除文件(为确保每次生成代码时都会删除所有 .pyc)。

我会这样做:

for name, module in sys.modules.iteritems():
    if name.startswith('my.dynamic.package.') and module is not None:
    try:    
        reload(module)
    except ImportError:
        pass

如果我的某些模块被删除了怎么办?我会按预期收到 ImportError,但我的模块是否已从运行时中删除?

【问题讨论】:

    标签: python reload


    【解决方案1】:

    不,reload 从不删除模块对象。它只是就地修改模块对象。因此,如果重新加载失败,旧绑定仍然保持不变。

    http://docs.python.org/2/library/functions.html#reload

    #so.py
    i = 0
    lis = [1,2,3]
    dic = {"a":1, "b":2}
    

    现在让我们导入这个模块:

    >>> import so
    >>> x = so.lis[0]  
    >>> so.lis[0]=0            #modify so.lis
    >>> so.dic["a"] = so.lis   #modify so.dic
    >>> !rm -r  so.py so.pyc   #delete both so.py and so.pyc 
    >>> try:                   #try reloading
    ...     reload(so)
    ... except ImportError:
    ...     pass
    ... 
    >>> so.lis                 #previous binding are still intact
    [0, 2, 3]
    >>> x
    1
    >>> so.dic
    {'a': [0, 2, 3], 'b': 2}
    

    现在我们将尝试修改模块而不是删除:

    #so.py
    i = 0
    lis = [1,2,3,4]
    dic = {"a":1, "b":2}
    

    现在导入它:

    >>> import so
    >>> lis = so.lis     #add a new reference to it
    >>> so.lis[0] = 0    #modify so.lis
    >>> so.i
    0
    

    现在将so.py修改为:

    #so.py
    i = 0
    lis = [1,2,3]       #updated lis
    dic = {"a":1, "b":2}
    

    现在reload():

    >>> reload(so)
    <module 'so' from 'so.py'>
    
    >>> so.lis       #got updated
    [1, 2, 3]
    >>> lis          #old so.lis object is still in memory as it's reference count is not 0
    [0, 2, 3, 4]
    

    【讨论】:

      【解决方案2】:

      --编辑:哎呀 Ashwini Chaudhary 比我快 :)

      在发布之前应该做更多的研究。

      我会回答我自己的问题:希望你们中的一些人会感兴趣。

      假设我已经导入了我的模块一次:

      import plop
      

      如果plop.pyplop.pyc 被删除:

      >>> reload(plop)
      ImportError: no module named plop
      

      但要小心!该模块不会从模块字典中删除。

      >>> print repr(sys.modules['plop'])
      <module 'plop' from plop.py>
      

      但是我可以手动删除它

      >>> del sys.modules['plop']
      >>> import plop
      ImportError: no module named plop
      

      在这种导入错误的情况下:无论我已经导入了模块,代码仍然绑定到导入时选择的局部变量名称 - 通常是模块名称。该模块仍然存在于我的运行时中。

      所以我又做了一些实验。

      如果我在代码中的某个地方碰巧从我的模块中导入了一个 函数,无论重新加载是否有效,我仍然会有 对旧函数的引用 .

      >>> from plop import somefunc
      >>> somefunc()
      i am the first version!
      >>> # code is regenerated
      >>> reload(plop)
      >>> # should print "i am the second version!"
      >>> somefunc()
      i am the first version!
      

      如果我使用 plop.somefunc() 代替,我将是最新的,以应对重新加载工作的情况。

      我的结论是:当我重新加载模块时,我应该始终小心并重新导入任何我需要使用的东西,无论是模块还是模块字段。如果重新加载失败,我应该清理 sys.modules 字典。

      【讨论】:

        猜你喜欢
        • 2019-11-16
        • 2016-10-18
        • 2016-12-12
        • 1970-01-01
        • 1970-01-01
        • 2013-04-29
        • 2012-02-27
        • 1970-01-01
        • 2013-10-05
        相关资源
        最近更新 更多