python – 也可以作为命令行脚本运行的包的结构
作者:互联网
我用the ‘standard’ minimal structure写了一个包.它看起来像这样:
my_package/
my_package/
__init__.py
setup.py
__init__.py包含一个类,因此可以像人们期望的那样简单地导入和使用.
但是,代码确实有助于以命令行方式使用,例如,
python my_package --arg1 "I like bananas."
起初,我只是在__init__中进行了if __name__ ==’__ main__’检查,然后使用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:尝试相对导入而没有已知的父包.
解决方法:
我想建议一个不同的结构:
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
这将调用demonst().
这条路:
>您不需要处理任何__main__文件
>您可以为脚本提供有意义的名称
>您不需要关心脚本是否可执行,或者指定使用python运行脚本
>您可以在列表entry_points中包含任意数量的这些内容
>它强制你编写你也可以从其他模块调用的函数,
而不是__main__
我觉得这很干净.
您可以在this blog中阅读有关entry_points的更多信息,它具有更多功能!
如果要使用__main__中指定的代码而不是此cli_scripts方法,可以查看this question.
标签:python,command-line,python-3-x,argparse,python-packaging 来源: https://codeday.me/bug/20190522/1152488.html