在python中导入外部模块的最佳实践

时间:2018-10-16 17:15:28

标签: python python-2.7

让我用一个简化的例子问这个问题。假设我在一个目录中有一个名为example.py的python2脚本,而我编写的其他脚本名为utils.py。在example.py中,我需要导入一个放置在/A/B/external.py路径下的外部模块。 “ A”和“ B”只是文件夹,不是包(不带__ init__.py)。最后,假设在/ A / B /下也有一个utils.py文件,并且是由external.py导入的。

如果我以熟悉的方式导入外部模块,我将这样做:

import sys
sys.path.append('/A/B/')
import external

问题是当我尝试导入 my utils模块时,python会在sys.modules dict中找到它(因为外部已将其导入),因此不会导入 my 脚本,但只有/ A / B下已导入的脚本。

现在,有解决方法。我可能会更改模块的名称,或将外部模块放入包装中,等等。但是,所有这些都感觉很脏。我找不到做这种事情的“ pythonic”最佳实践。就像您中某些人所猜到的那样,在更复杂的情况下可能会导致非常令人讨厌的错误。 此外,PEP8不接受我熟悉的方式,因为模块顶部没有导入命令。

总而言之,谢谢,我正在寻找最佳做法。

1 个答案:

答案 0 :(得分:0)

尽管已经过去了将近两年,但据我所知,我想描述正确的答案。 TL; DR::最好的方法是完全避免操纵sys.path(!),而改用分发打包机制。

首先,让我们区分distribution-package和import-package。 导入包基本上是一个包含pythonic模块的目录(即.py / .pyc文件)和一个__init__.py文件,用以声明此文件夹确实是一个包。在问题的示例中,这是包含example.pyutils.py的目录。与此相反,分发包是:

版本化的存档文件,其中包含用于分发发行版的Python软件包,模块和其他资源文件。

来源:PyPA user guideglossary

另一个应该知道的术语是脚本。 python脚本是__main__ python文件,可直接通过解释器运行(而其他python文件称为 modules )。来源:python's docs

在您自己的导入程序包中,您不应编辑sys.path,因为脚本文件会导入相对于文件位置的模块,这是所需的行为。如果您打算从导入包外部使用另一个模块(并且让我清楚地说,不是从当前导入包内部的另一个导入包导入的情况,这是正常现象并且效果很好),那么您应该将其作为已安装的分发程序包导入。

我的意思是,外部代码(在示例中,位于A / B /下的external.py模块)应该作为分发程序包(其 maintainers > 应该将其作为软件包上传到某种分发机制(即PyPi),这很可能是您,但作为另一个软件包开发者)。然后-您作为外部软件包 user 应当安装它(例如,在该外部分发软件包的wheel文件中使用pip install),然后将其添加到您的环境中并进行管理,因此您可以import external,并且不会发生冲突。