我已经用the 'standard' minimal structure编写了一个程序包。看起来像这样:
my_package/
my_package/
__init__.py
setup.py
__init__.py
包含一个类,因此可以像预期的那样简单地导入和使用。
但是,代码确实适合在命令行中使用,例如
python my_package --arg1 "I like bananas."
首先,我刚刚在if __name__ == '__main__'
中进行了__init__
的签入,然后将使用argparse
。这个有用,但是它不是很漂亮,因为这意味着您可以像这样从命令行调用它:
python my_package/__init__.py --arg1 "I like bananas."
据我了解,这是一个__main__.py
文件所在的位置,它将作为文件夹内的默认脚本执行(类似于网站上的index.html
文件)。我的想法是然后简单地导入__init__.py
,运行argparse并将参数提供给类构造函数。像这样:
import argparse
from __init__ import MyClass
parser = argparse.ArgumentParser()
parser.add_argument("--arg1", help="Some dummy value")
args = parser.parse_args()
my_class = MyClass(**vars(args))
my_class.do_stuff()
这是应该如何构造相似的程序包,还是有更好的方法?
上面的作品但是 PyCharm告诉我,__main__.py
__init__
是一个未解决的引用。在该导入行上与MyClass
相同。当我改用.__init__
(带点)时,警告消失了,但是代码不再起作用,给了我ImportError: attempted relative import with no known parent package
。
答案 0 :(得分:4)
我想为您建议一个不同的结构:
my_package/
my_package/
__init__.py
cli_scripts.py
setup.py
让我们假设您的__init__.py
如下所示(作为补充,我建议将其中定义的类移动到单独的文件中,然后将其导入__init__
中):
class Test(object):
def __init__(self, a)
self.a = a
def __call__(self):
print(self.a)
现在,程序包中还有一个附加文件,它利用了您在程序包中实现的内容,我们将其称为cli_scripts.py
:
import argparse
from my_package import Test
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("a", type=int, help="Just an example argument")
return parser.parse_args()
def demonstration():
args = parse_args()
t = Test(a=args.a)
t()
我现在的建议是利用setup.py
中的console_scripts entry point,现在看起来像这样:
from setuptools import setup
setup(
name='testpy',
version='0.1',
description='Just an example',
author='RunOrVeith',
author_email='xyz@mailinator.com',
packages=["my_package"],
entry_points={
"console_scripts": ["mypkg=my_package.cli_scripts:demonstration"]},
install_requires=[],
)
现在,当您在顶级pip install .
文件夹中运行my_package
时,将安装软件包。 entry_points
将自动为您生成一个可执行文件,您现在可以使用在setup.py
(在本示例中为mypkg
)中为其指定的名称进行调用。这意味着您现在可以运行
mypkg 5
这将称为demonstration()
。
这种方式:
__main__
个文件python
运行脚本entry_points
内可以有任意数量的__main__
我认为这很干净。
您可以在this blog中阅读有关entry_points
的更多信息,它具有更多功能!
如果您想使用__main__
中指定的代码而不是这种cli_scripts
方法,可以看看this question。