【问题标题】:Python best practices for Importing module inside my package在我的包中导入模块的 Python 最佳实践
【发布时间】:2021-11-10 03:16:56
【问题描述】:

我对 Python 打包路径系统有点困惑(实际上很多)。

我有这个项目:

myproject/
    package1/
       setup.py
       src/
          __init__.py
          module1.py
          module2.py
          module3.py
       tests/
          __init__.py
          test_package1.py

    package2/
       setup.py
       src/
          __init__.py
          module1.py
          module2.py
          module3.py
       tests/
          test_package2.py

    package3/
       setup.py
       src/
          __init__.py
          module1.py
          module2.py
          module3.py
       tests/
          test_package3.py

这些包应该在 CI 过程之后发布到私有存储库中(如果测试通过)。

重要提示: Package1 使用 package2,而 package2 使用 package3。

所以 package1 的 setup.py 看起来像这样:

setuptools.setup(
    name='package1',
    version='1.4.0.dev1',
    install_requires=['setuptools~=50.3.2',
                      'boto3~=1.17.0',
                      'pandas~=1.3.4',
                      'package2~=1.4.0.dev1'],
    package_dir={"package1": "src"},
    packages=["package1"],
    include_package_data=True,
    setup_requires=['pytest-runner'],
    tests_require=['pytest'],
    python_requires=">=3.6"
)

setup.py 的 package2 看起来像这样:

setuptools.setup(
    name='package2',
    version='1.4.0.dev1',
    install_requires=['PyYAML~=5.3.1'
                      'package3~=1.4.0.dev1'],
    package_dir={"package2": "src"},
    packages=["package2"],
    include_package_data=True,
    setup_requires=['pytest-runner'],
    tests_require=['pytest'],
    python_requires=">=3.6"
)

CI 流程:

  1. 我正在为每个包运行pip install .(来自相应的包目录)
  2. 从 package3 目录运行测试:python -m pytest tests -vvv
  3. 从 package2 目录运行测试:python -m pytest tests -vvv
  4. 从 package1 目录运行测试:python -m pytest tests -vvv

package2 和 package3 的测试成功通过,但最后一步 - 为 package1 运行 pytest 时,它会在 package2 中的 ModuleNotFoundError 上报错:

module1.py(package2):

from module2 import AwsService
...

AwsService 只是module2.py 中定义的一个类。

我将导入更改为:from . import AwsService,重新安装包并再次重新运行 package1 测试。这次pytest抱怨package3中的import:

module1.py(package3):

import module2
...

所以我将导入更改为from . import module2 并开始运行测试。

但是在 package2 的 module3 中我有 from module2 import AwsService 并且没关系,那么我怎么知道什么时候必须进行相对导入,什么时候不需要呢?!。

我对所有这些路径行为感到完全困惑。

也许我的setup.py 不好或项目结构或我测试它的方式不好?

【问题讨论】:

  • _init_.py 应该是 __init__.py。并且约定src/ 通常以包命名,因此package1/ 等而不是src/
  • 请注意,安装时不应依赖 requirements.txt。这应该在setup.py (setup_requires) 中,然后是每个包的pip install .(在它们各自的包目录中)。不过测试略有不同。
  • 你的问题很可能是因为包没有正确安装,PYTHONPATH设置错误(或不存在),包找不到对方。在内部,包可以找到自己的模块,但不能从其他包中找到。您确实提到 package3 依赖于(导入)package2,但是否经过测试和验证?

标签: python python-3.x pytest


【解决方案1】:

我的问题的解决方案只是将 myproject 的路径分配给 PYTHONPATH:

export PYTHONPATH=/Users/yuri/projects/myproject/

当您通过pip install . 在本地安装包并执行pip freeze 时,您将看到您的包已安装,但您还会看到您的包附近的路径,路径如下:file:///Users/yuri/projects/myproject/package1 作为参考原始位置,Python 看不到它。所以你必须手动添加路径。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    • 2016-10-12
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多