修改 Python 模块的常见做法

Posted

技术标签:

【中文标题】修改 Python 模块的常见做法【英文标题】:Common practices for modifying Python modules 【发布时间】:2012-12-28 23:43:17 【问题描述】:

我有一个 Python 模块测试,我想编辑测试并在​​解释器的测试中运行一些函数。 Python 会自动查看我在测试中编辑的函数的差异而不重新导入吗?这个动作的合适词是什么?

    重新导入/重新加载/重新定义的最佳做法是什么? 如何有效地做到这一点? (用鼠标突出显示文本然后复制和粘贴似乎效率低下)。

编辑到目前为止没有提到任何工作,所以我将发布更多细节:

我的模块中有一个类,称为 Test。所以我使用了声明from test import Test。现在,当我尝试命令reload(test) 时,解释器告诉我重新加载未定义。如果我做import imp 然后imp.reload(test) 解释器告诉我test 是未定义的。这里出了什么问题?

【问题讨论】:

可能重复:How do I unload (reload) a Python module? 【参考方案1】:

假设有一个名为 data.py 的模块包含:

def foo():pass
In [13]: import data

In [14]: dir(data)
Out[14]: ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'foo']

现在向 data.py 添加另一个函数,同时 shell 仍在运行:

def foo():pass
def bar():pass
In [15]: import data

In [16]: dir(data)     #new function bar is not fetched by the import
                       #coz it simply loads the data object already present in memory

Out[16]: ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'foo']

使用imp.reload() 重新加载模块对象。

In [17]: import imp

In [18]: imp.reload(data)
Out[18]: <module 'data' from 'data.py'>

In [19]: dir(data)
Out[19]: 
['__builtins__',
 '__doc__',
 '__file__',
 '__name__',
 '__package__',
 'bar',
 'foo']          # bar fetched

help()reload():

重新加载(模块)-> 模块

重新加载模块。模块必须已成功导入 之前。

【讨论】:

@CodeKingPlusPlus from test import Test 等价于import test;Test=test.Test;del test,因此内存中没有为reload() 预加载的模块,您的代码将失败。【参考方案2】:

嗯,对于初学者来说,您绝对应该有一个名为 test 的模块,因为 Python 的标准库中已经有一个。

test 未定义,因为您导入了 Test,而不是 test。你也需要import test

但请注意,由于imp.reload() 的工作方式,重新加载test 不会更新Test;那仍将引用该类的旧副本。你也必须再次from test import Test

事件的完整序列:

>>> import imp
>>> import test
>>> from test import Test
>>> Test().whatever()
# edit your code
>>> imp.reload(test)
>>> from test import Test  # or: Test = test.Test
>>> Test().whatever()

这个故事的寓意是reload 很糟糕,你应该不惜一切代价避免它。如果您想在每次编辑库后重新运行一堆代码,只需将该代码放入一个文件并运行它。

【讨论】:

【参考方案3】:

我怀疑您使用的是 Python 3,而所有回答者都假设您使用的是 Python 2。

在 Python 3 中,reloadbuiltins 移动到 imp

所以,答案是:

imp.reload(test)

为了将来参考,如果您使用的是 Python 3,几乎总是值得一提,除非您知道它不相关,因为许多老前辈(阅读:您想要回答的人)将假定为 2.7。

同时,回到你的主要问题:

重新导入/重新加载/重新定义的最佳做法是什么?

对于简单的情况,reload()imp.reload() 正是您想要的。 (对于超级——简单的情况,复制粘贴没什么问题……)

但是当你有一些对象bar 的类foo.Bar 然后重新加载foo 时很容易混淆自己。它也不能很好地与 from foo import * 配合使用,这对于交互式会话来说通常很方便。

如果您可以启动一个新的解释器会话并导入模块,那就更干净了。如果您需要创建一堆对象来开始使用模块,您可以将它们作为全局变量临时添加到模块中,或者创建一个定义它们的包装器模块。一些 IDE 可以封装所有这些,因此只需按一些加速键序列即可使其重新启动解释器并重新运行您的 import 和所有设置内容。

【讨论】:

【参考方案4】:

Python 是否会自动查看我在测试中编辑的函数的差异而无需重新导入?

没有。

这个动作的合适词是什么?

查看内置reload(module)。

【讨论】:

以上是关于修改 Python 模块的常见做法的主要内容,如果未能解决你的问题,请参考以下文章

python configparse 模块

configparser模块——用于生成和修改常见配置文档

Python ConfigParser模块

python模块之hashlib

常见模块 os模块

求解汉诺塔问题修改版