在Python中正确导入模块

11 投票
4 回答
18752 浏览
提问于 2025-04-15 11:45

我该如何设置模块导入,以便每个模块都能访问其他模块的对象呢?

我有一个中等规模的Python应用程序,里面有很多子目录的模块文件。我创建了一些模块,把这些子目录添加到sys.path中,并用import thisModule as tm导入一组模块。模块对象通过这种方式来引用。然后,我又用from moduleImports import *把那个模块导入到其他模块中。现在代码有点乱,里面有很多重复的部分。

首先,应用程序出错了,因为有些模块引用没有被正确赋值。不过,这段代码在单元测试时是可以运行的。

其次,我担心我可能引发了递归导入的问题。导入moduleImports会导入thisModule,而thisModule又会导入moduleImports……

那么,正确的做法是什么呢?

4 个回答

4

要做到这一点,关键是要避免神秘的操作。换句话说,如果你的模块需要其他模块的某些东西,就应该明确地导入它。不要依赖于某些东西会自动被导入。

正如Python的哲学所说(可以通过输入import this查看),明确的做法总是比隐含的做法要好。

6

几点建议

  1. 你可能已经把功能分成了不同的模块。如果分得好,大部分情况下你就不会遇到循环导入的问题(比如,如果模块a依赖于b,而b又依赖于a,你可以创建一个第三个模块c来消除这种循环依赖)。如果实在没有办法,先在a中导入b,然后在b中在需要a的地方再导入a,比如在函数内部。

  2. 一旦功能正确地放在模块里,就把它们放在一个子目录下的包中,并添加一个__init__.py文件,这样你就可以导入这个包了。把这些包放在一个文件夹里,比如叫lib,然后要么把它添加到sys.path,要么设置PYTHONPATH环境变量。

  3. 使用from module import *可能不是个好主意。相反,应该只导入需要的东西。可以使用完整的路径,详细一点也没关系。比如,from packageA.moduleB import CoolClass

24

“我有一个中等规模的Python应用程序,里面有多个子目录的模块文件。”

很好。一定要确保每个目录里都有一个 __init__.py 文件,这样它才能被当作一个包来使用。

“我创建了模块来将这些子目录添加到 sys.path 中。”

不好。应该使用 PYTHONPATH 或者把整个结构安装到 Lib/site-packages 里。不要动态地更新 sys.path,这样做不好,管理和维护起来很麻烦。

“我用 import thisModule as tm 导入一组模块。”

这没什么意义。也许你对结构中的每个模块都有一个 import thisModule as tm。这是一种典型的标准做法:只导入你需要的模块,不要导入其他的。

“然后我用 from moduleImports import * 将那个模块导入到其他模块中。”

不好。不要随便导入一堆随机的东西。

每个模块应该有一个较长的具体需求列表。

import this
import that
import package.module

要明确列出需要的内容。不要有魔法,也不要动态改变 sys.path

我现在的项目有数百个模块,十几个包。每个模块只导入它需要的内容。没有魔法。

撰写回答