在多模块项目中设置导入和__init__.py

时间:2017-02-21 10:20:16

标签: python

问题

我已经发现了很多关于在Python中使用import的基础知识的文章和教程,但没有一篇能提供有关使用多个软件包设置自己的Python项目的全面指南。

这是我项目的结构:

  • codename/
    • __init__.py
    • package1.py(有class1并且是一个脚本)
    • package2.py(有class2
    • package3.py(有function1并且是一个脚本)
  • test/
    • __init__.py
    • test_package1.py(具有package1的单元测试)
    • test_package3.py(具有package3的单元测试)

如何设置导入以满足以下要求(并且所有这些要求都有意义?):

  1. class1class2function1位于名称空间codename中,即可行:

    import codename
    obj = codename.class1()
    codename.function1(obj)
    
  2. 可以使用from codename import *from codename import class1

  3. 以相同方式导入它们
  4. function1可以轻松访问class1(如何?)
  5. package1package2是可执行脚本
  6. test_package1.pytest_package3.py
  7. 也是如此
  8. 测试也可通过python -m unittest discover
  9. 执行
  10. 脚本也可通过python -m codename.package1
  11. 执行

    出于某些原因,我遇到了遇到所有这些问题的问题,当我尝试修复一个问题时,会弹出另一个问题。

    我尝试了什么?

    • 离开codename/__init__.py空满足几乎所有要求,因为一切正常,但在模块的命名空间中留下class1之类的名称 - 而我想要它们导入包装。
    • 再次添加from codename.package1 import class1等满足大多数要求,但在通过python -m codename.package1执行脚本时收到警告:

      RuntimeWarning: 'codename.package2' found in sys.modules \
      after import of package 'codename', but prior to execution of \
      'codename.package2'; this may result in unpredictable behaviour
      

    哪种有道理...... 通过python codename/package1.py函数运行脚本,但我想我可能希望两种方式都可以工作。

    • 我遇到an answer to a similar question说明内部模块也不应该是脚本,但我不明白为什么我们会接到-m开关?无论如何,将main提取到外部scripts目录中是有效的,但这是设置所有这些的唯一规范方法吗?

1 个答案:

答案 0 :(得分:1)

  1. 您需要将codename/的父目录添加到PYTHONPATH环境变量(或编写/使用setup.py文件,或修改{{1在运行时)

  2. 您需要在sys.path

  3. 中导入要导出的所有名称
  4. codename/__init__.py如果你写/使用from .package1 import function1文件,否则setup.py

  5. 您应该使用from codename.package1 import function1文件作为脚本/可执行文件,因为它可以使所有内容更加清晰(无论如何您迟早都需要setup.py文件)

  6. (和6.)我建议使用setup.py它会自动找到所有测试(并且可以并行运行等)。

  7. 这应该是开箱即用的,但如果您已经写了py.test,那么您可以在任何地方(以及在任何平台上)运行它们,只需{{1} }。