python - 防止 Python 缓存导入的模块

标签 python import ipython python-module python-import

在使用 IPython 在 Python 中开发大型项目(拆分为多个文件和文件夹)时,我遇到了缓存导入模块的问题。

问题是指令 import module 只读取该模块一次,即使该模块已更改!所以每次我更改包中的某些内容时,我都必须退出并重新启动 IPython。很痛苦。

有没有办法正确强制重新加载某些模块?或者,更好的是,以某种方式阻止 Python 缓存它们?

我尝试了几种方法,但都没有奏效。特别是我遇到了非常非常奇怪的错误,比如一些模块或变量神秘地等于 None...

我发现的唯一合理资源是 Reloading Python modules ,来自pyunit,但我没有检查过。我想要这样的东西。

一个不错的选择是让 IPython 重新启动,或者以某种方式重新启动 Python 解释器。

那么,如果你用 Python 开发,你找到了解决这个问题的方法吗?

编辑

为了清楚起见:显然,我知道一些旧变量取决于模块的先前状态可能会保留。那个我能接受。为什么在 Python 中强制重新加载模块而不发生各种奇怪的错误如此困难?

更具体地说,如果我将整个模块放在 one 文件 module.py 中,则以下内容可以正常工作:

import sys
try:
    del sys.modules['module']
except AttributeError:
    pass
import module

obj = module.my_class()

这段代码运行良好,我可以在几个月内不退出 IPython 的情况下进行开发。

然而,每当我的模块由几个子模块组成时, hell 就会崩溃:

import os
for mod in ['module.submod1', 'module.submod2']:
    try:
        del sys.module[mod]
    except AttributeError:
        pass
# sometimes this works, sometimes not. WHY?

为什么我的模块在一个大文件或多个子模块中对 Python 来说如此不同?为什么这种方法行不通??

最佳答案

import 检查模块是否在 sys.modules 中,如果是,则返回它。如果要导入以从磁盘加载模块,可以先删除 sys.modules 中的相应键。

有一个 reload 内置函数,它会在给定一个模块对象的情况下,从磁盘重新加载它,并将其放置在 sys.modules 中。 Edit -- 实际上,它会从磁盘上的文件中重新编译代码,然后在现有模块的 __dict__ 中重新评估它。可能与创建新模块对象非常不同。

不过,迈克·格雷厄姆是对的;如果您甚至有一些事件对象引用了您不再需要的模块内容,那么要正确地重新加载是很困难的。现有对象仍将引用它们被实例化的类是一个明显的问题,但通过 from module import symbol 创建的所有引用仍将指向旧版本模块中的任何对象。许多微妙的错误都是可能的。

编辑:我同意重启解释器是迄今为止最可靠的事情的共识。但是出于调试目的,我想您可以尝试以下方法。我确信在某些极端情况下这是行不通的,但是如果您在 your 包中加载模块时没有做任何太疯狂的事情(否则),它可能会很有用。

def reload_package(root_module):
    package_name = root_module.__name__

    # get a reference to each loaded module
    loaded_package_modules = dict([
        (key, value) for key, value in sys.modules.items() 
        if key.startswith(package_name) and isinstance(value, types.ModuleType)])

    # delete references to these loaded modules from sys.modules
    for key in loaded_package_modules:
        del sys.modules[key]

    # load each of the modules again; 
    # make old modules share state with new modules
    for key in loaded_package_modules:
        print 'loading %s' % key
        newmodule = __import__(key)
        oldmodule = loaded_package_modules[key]
        oldmodule.__dict__.clear()
        oldmodule.__dict__.update(newmodule.__dict__)

我这样简单地测试过:

import email, email.mime, email.mime.application
reload_package(email)

打印:

reloading email.iterators
reloading email.mime
reloading email.quoprimime
reloading email.encoders
reloading email.errors
reloading email
reloading email.charset
reloading email.mime.application
reloading email._parseaddr
reloading email.utils
reloading email.mime.base
reloading email.message
reloading email.mime.nonmultipart
reloading email.base64mime

关于python - 防止 Python 缓存导入的模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2918898/

相关文章:

python - 我将如何解决此 Python 代码中的 'list index out of range' 错误?

python - 用于安全密码处理的 pyside 小部件

python - 如何使用networkx nx.draw()使x轴和y轴出现?

jquery - CORS 与 python baseHTTPserver 501(不支持的方法 ('OPTIONS'))在 chrome

python - 交互式 IPython 终端中连续运行的 Tensorflow Op 命名

python - jupyter notebook 在评估 cell 后跳转

scala - Scala,导入类

python - python如何导入类名

python - 从 python 2.7 中的包导入名称、子模块或子包的优先级是什么?

ipython - 无法打开 IJulia;它改为启动 IPython