use*_*446 5 python project python-import python-3.x
我已经阅读了很多关于 Python 导入(以及相关的 SO 问题)的“操作方法”文章,但是我正在努力弄清楚在大型 Python 项目中管理导入的“最佳实践”是什么。例如,假设我有一个如下所示的项目结构(这是一个过度简化):
test/
packA/
subA/
__init__.py
sa1.py
sa2.py
__init__.py
a1.py
a2.py
packB/
b1.py
b2.py
main.py
Run Code Online (Sandbox Code Playgroud)
并在里面说packA/subA/sa1.py我想从packB/b1.py. 更一般地说,我希望能够在项目内的包/子包之间自由导入。
根据我目前的理解,有四种方法可以做到这一点:
将我的项目根永久添加到 PYTHONPATH 并在项目中的任何地方使用绝对导入。所以在 packA/subA/sa1.py 里面我会有
from packB import b1
随着项目树变大,这可能会变得有点混乱,例如
from packB.subC.subD.subE import f1
与上面相同,但我没有修改 PYTHONPATH 以包含项目根目录,而是坚持只从项目根目录执行 python(以便根目录始终是工作目录)。
使用相对导入
from ...packB import b1
我不喜欢这样,因为它不容易阅读,而且我读过的所有地方都说相对导入是个坏主意。
使用 setuptools/setup.py 脚本并使用 pip 安装我的包,以便我可以在任何地方导入。
这似乎有点矫枉过正,因为所有代码都已经在项目文件夹中(并且每次包更改时都必须重新安装),并且还可能导致依赖项/版本管理的麻烦。
所以我的问题是,以上哪一个(如果有)被认为是最佳实践?我目前在 1 和 2 之间犹豫不决,但很高兴听到更优雅/Pythonic 的方法。
注意:我使用的是 Python 3.6
您可以做的第一件事是重新设计您的包。说真的,直接来自pep20 python zen:
扁平比嵌套好。
因此,您应该尝试减少包中嵌套文件夹的数量。例如from mypackage.module1.module2.module3 import foo不应该存在。唯一一次您会看到模块嵌套在非常大且成熟的包中,例如django或tensorfow。即便如此,您仍会注意到它们的 api 仍然非常短(即from django.test import TestCase),即使它们的内部模块很复杂且嵌套。通常,长导入和嵌套导入是 Python 中包设计不良的信号。
此外,如果包 A 和包 B 相互依赖(相互依赖),它们应该确实在同一个包下,您需要重新考虑您的设计选择。
我总是喜欢遵循flask或keras库中的标准。该keras特别API一直直观的给我。我经常去那个 repo 来激发我自己的编码实践。就我个人而言,我尝试尽可能使用相对导入,因为我构建的大多数东西都很小(没有嵌套,或者只有一层嵌套)。但是我知道许多较大的项目选择使用绝对导入,因为它们有更多的嵌套层。
我从 'keras' 库中采用的一件事是在进口的特异性和可用性之间取得平衡。要导入Conv2D图层,它并不像以下一般:
from keras import Conv2D,
但它也不是那么具体:
from keras.layers.convolational import Conv2D
中间有一个很好的:
from keras.layers import Conv2D.
但是,如果我们仔细查看keras,您会注意到Conv2D该类仍然包含在它自己的文件中convolutional.py。他们可以通过__init__.py在图层模块的中添加以下行来降低导入的特异性:
from .convolutional import Conv2D
Run Code Online (Sandbox Code Playgroud)
这允许您保留用于开发的包/模块结构,但保持客户端 api 简单直观。
绝对不要选择选项 1。 pip 包的目的是您不需要向PYTHONPATH. 这不是可扩展的,这意味着如果不编辑PYTHONPATH. 最好setup.py在每个包中都有一个并通过pip.
这是超级讨厌保持不必pip uninstall .和pip install .的每次你改变你的包,所以这就是为什么pip有-e标志:
pip install -e .
Run Code Online (Sandbox Code Playgroud)
该-e标志是一个可编辑的安装,它安装包,以便您对代码所做的任何更改立即生效,因此您不必pip在进行更改后继续卸载和重新安装。
| 归档时间: |
|
| 查看次数: |
3076 次 |
| 最近记录: |