简体   繁体   English

包的正确 Python 项目结构

[英]Correct Python project structure for packages

I am creating a Python utility that will need to be shared internally via pip packages, and will be consumed both as a library and as a command-line tool.我正在创建一个 Python 实用程序,该实用程序需要通过pip包在内部共享,并将作为库和命令行工具使用。

I am having difficulty with the correct use of namespaces and where/when/if to put __init__.py files to get a consistent codebase.我在正确使用命名空间以及放置__init__.py文件以获取一致的代码库时遇到困难。

  • I can get "library" usage working, so I can from example_service.example import Example .我可以让“库”使用工作,所以我可以from example_service.example import Example
  • I can get CLI usage working, so I can execute python example_service/example_cli.py .我可以使用 CLI,所以我可以执行python example_service/example_cli.py
  • I can get pytest working.我可以让pytest工作。
  • I CANNOT get all three working at once.我不能同时让所有三个工作。

So所以

  • Should my package's use from filename import Class or from.filename or from example_service.filename ?我的包应该使用from filename import Class还是from.filenamefrom example_service.filename
  • Should I put a __init__.py in my package directory or not?我应该在我的 package 目录中放置一个__init__.py吗? It seems it should not be necessary for Python3, but I get mixed results.似乎 Python3 不需要它,但我得到的结果好坏参半。

  • If如果
    • example.py uses from componenta import ComponentA and example.py使用from componenta import ComponentA
    • example_cli.py uses from example import Example example_cli.py使用from example import Example
    • then the CLI invokation works然后 CLI 调用工作
    • the library import fails with no component named 'componenta'库导入失败no component named 'componenta'
  • If如果
    • example.py uses from example_service.componenta import ComponentA and example.py使用from example_service.componenta import ComponentA
    • example_cli.py uses from example import Example example_cli.py使用from example import Example
    • then the CLI invokation fails with no component named 'example_service'然后 CLI 调用失败no component named 'example_service'
    • the library import works图书馆导入工作

I currently have a project directory that looks something like this:我目前有一个看起来像这样的项目目录:

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

Inside my main lib code, example.py , I have:在我的主库代码example.py中,我有:

from componenta import ComponentA

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

My CLI wrapper will handle args and stuff, but for now is just:我的 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()

And componenta.py is:componenta.py是:

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

(Full code has been posted to GitHub ) (完整代码已发布到GitHub

A couple of points:几点:

  • It's true that a package without __init__.py should work (since Python 3.3 I think).确实,没有__init__.py的 package 应该可以工作(因为我认为 Python 3.3)。 You can leave it out, if you don't need it (ie: you have nothing to write in it).如果您不需要它,您可以将其省略(即:您无需在其中写入任何内容)。

  • I would not call python example_service/example_cli.py directly, ever.我永远不会直接调用python example_service/example_cli.py You have the setuptools entry point for this purpose, so in your case call example directly instead.您有用于此目的的setuptools入口点,因此在您的情况下直接调用example (You can remove the shebang and the executable bit from example_service/example_cli.py .) (您可以从example_service/example_cli.py中删除 shebang 和可执行位。)

  • from within your package example_service you can either use from example_service.componenta import ComponentA or from.componenta import ComponentA .从 package example_service中,您可以使用from example_service.componenta import ComponentAfrom.componenta import ComponentA This should work the same in both cases.这在两种情况下应该是一样的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM