【问题标题】:Correct Python project structure for packages正确的包的 Python 项目结构
【发布时间】:2019-10-02 22:48:33
【问题描述】:

我正在创建一个 Python 实用程序,它需要通过 pip 包在内部共享,并将作为库和命令行工具使用。

我在正确使用命名空间以及将 __init__.py 文件放置在何处/何时/是否放置以获得一致的代码库方面遇到困难。

  • 我可以使用“库”,所以我可以from example_service.example import Example
  • 我可以使用 CLI,因此我可以执行 python example_service/example_cli.py
  • 我可以让pytest 工作。
  • 我无法同时让所有三个工作。

所以

  • 我的包裹应该使用from filename import Classfrom .filenamefrom example_service.filename吗?
  • 我是否应该将__init__.py 放在我的包目录中? Python3 似乎不需要它,但我得到的结果好坏参半。

  • 如果
    • example.py 使用 from componenta import ComponentA
    • example_cli.py 使用 from example import Example
    • 然后 CLI 调用工作
    • 库导入失败no component named 'componenta'
  • 如果
    • example.py 使用 from example_service.componenta import ComponentA
    • example_cli.py 使用 from example import Example
    • 然后 CLI 调用 失败 并显示 no component named 'example_service'
    • 库导入有效

我目前有一个看起来像这样的项目目录:

project_root/
    example_service/
        example.py
        example_cli.py
        componenta.py
        componentb.py
        tests/
            __init__.py
            test_example.py
    setup.py
    requirements.txt

在我的主库代码example.py 中,我有:

from componenta import ComponentA

class Example(object):
    def foo(self):
        a = ComponentA()
        print("Example.foo()")

我的 CLI 包装器将处理 args 和其他东西,但现在只是:

#!/usr/bin/env python
from example import Example

class ExampleCli(object):
    def __init__(self):
        print("ExampleCli.init()")
        e = Example()
        e.foo()

if __name__ == '__main__':
    ExampleCli()

componenta.py 是:

class ComponentA(object):
    def bar(self):
      print("ComponentA.bar()")

(完整代码已发布到GitHub

【问题讨论】:

  • 还有问题吗?我克隆了您的存储库,一切似乎都正常。
  • @sinoroc 这是一个愚蠢的环境问题。我刚刚忘记pip install -e .

标签: python python-3.x pip setuptools


【解决方案1】:

几点:

  • 确实,没有__init__.py 的包应该可以工作(我认为是从 Python 3.3 开始)。如果你不需要它,你可以把它省掉(即:你没有什么可写的)。

  • 我永远不会直接打电话给python example_service/example_cli.py。为此,您有 setuptools 入口点,因此在您的情况下,请直接调用 example。 (您可以从example_service/example_cli.py 中删除shebang 和可执行位。)

  • 在您的包example_service 中,您可以使用from example_service.componenta import ComponentAfrom .componenta import ComponentA。这在两种情况下应该是一样的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-06
    • 2016-06-26
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-01
    相关资源
    最近更新 更多