[英]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
文件以获取一致的代码库时遇到困难。
from example_service.example import Example
.from example_service.example import Example
。python example_service/example_cli.py
.python example_service/example_cli.py
。pytest
working.pytest
工作。 So所以
from filename import Class
or from.filename
or from example_service.filename
?from filename import Class
还是from.filename
或from example_service.filename
?__init__.py
in my package directory or not?__init__.py
吗? It seems it should not be necessary for Python3, but I get mixed results.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
no component named 'componenta'
no component named 'componenta'
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
no component named 'example_service'
no component named 'example_service'
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()")
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 ComponentA
或from.componenta import ComponentA
。 This should work the same in both cases.这在两种情况下应该是一样的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.