在Python中正确导入模块
我该如何设置模块导入,以便每个模块都能访问其他模块的对象呢?
我有一个中等规模的Python应用程序,里面有很多子目录的模块文件。我创建了一些模块,把这些子目录添加到sys.path
中,并用import thisModule as tm
导入一组模块。模块对象通过这种方式来引用。然后,我又用from moduleImports import *
把那个模块导入到其他模块中。现在代码有点乱,里面有很多重复的部分。
首先,应用程序出错了,因为有些模块引用没有被正确赋值。不过,这段代码在单元测试时是可以运行的。
其次,我担心我可能引发了递归导入的问题。导入moduleImports会导入thisModule,而thisModule又会导入moduleImports……
那么,正确的做法是什么呢?
4 个回答
要做到这一点,关键是要避免神秘的操作。换句话说,如果你的模块需要其他模块的某些东西,就应该明确地导入它。不要依赖于某些东西会自动被导入。
正如Python的哲学所说(可以通过输入import this
查看),明确的做法总是比隐含的做法要好。
几点建议
你可能已经把功能分成了不同的模块。如果分得好,大部分情况下你就不会遇到循环导入的问题(比如,如果模块a依赖于b,而b又依赖于a,你可以创建一个第三个模块c来消除这种循环依赖)。如果实在没有办法,先在a中导入b,然后在b中在需要a的地方再导入a,比如在函数内部。
一旦功能正确地放在模块里,就把它们放在一个子目录下的包中,并添加一个
__init__.py
文件,这样你就可以导入这个包了。把这些包放在一个文件夹里,比如叫lib,然后要么把它添加到sys.path,要么设置PYTHONPATH环境变量。使用
from module import *
可能不是个好主意。相反,应该只导入需要的东西。可以使用完整的路径,详细一点也没关系。比如,from packageA.moduleB import CoolClass
。
“我有一个中等规模的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
。
我现在的项目有数百个模块,十几个包。每个模块只导入它需要的内容。没有魔法。