【问题标题】:Setting up imports and __init__.py in a multi-module project在多模块项目中设置导入和 __init__.py
【发布时间】:2017-02-21 10:20:15
【问题描述】:

问题

我找到了几十篇关于在 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. function1 可以轻松访问class1(如何?)
  4. package1package2 是可执行脚本
  5. test_package1.pytest_package3.py 也是如此
  6. 测试也可以通过python -m unittest discover执行
  7. 脚本也可以通过python -m codename.package1 执行

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

我尝试了什么?

  • 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 开关?无论如何,将mains 提取到外部scripts 目录中是可行的,但这是设置所有这些的唯一规范方法吗?

【问题讨论】:

    标签: python


    【解决方案1】:
    1. 您需要将codename/ 的父目录添加到PYTHONPATH 环境变量(或写入/使用setup.py 文件,或在运行时修改sys.path

    2. 您需要在codename/__init__.py中导入所有要导出的名称

    3. from .package1 import function1 如果您编写/使用setup.py 文件,否则from codename.package1 import function1

    4. 您应该为脚本/可执行文件使用 setup.py 文件,因为它可以让一切变得更加整洁(而且您迟早会需要一个 setup.py 文件)

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

    6. 这应该是开箱即用的,但是如果您编写了setup.py,那么您可以在任何地方(和任何平台)运行它们,就像package1一样。

    【讨论】:

    • 3.这不起作用。我添加了一个 setup.py 文件,同时使用了 install 和 development 并且在正常运行脚本时我得到了No module named '__main__.package1'; __main__ is not a package,在from .package1 import... 行上得到了Cannot import name 'package1'。但无论如何,通过查看 setup.py 的文档,我猜这是一个标准程序,将脚本与模块分开而不使用 -m:是这样吗?
    • 您需要使用setup.pyentry_points 功能,例如github.com/thebjorn/pydeps/blob/master/setup.py(语法为 command_name = importable.dotted.path:function_name)。
    • 啊,现在可以了!谢谢一堆。我还发现了一篇关于在 python 项目中设置可执行文件的非常有用的文章:chriswarrick.com/pl/blog/2014/09/15/…
    • 不错的资源。谢谢。
    猜你喜欢
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    • 2013-04-21
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    相关资源
    最近更新 更多