python - 如何打包 Python 项目以在控制台中运行
问题描述
我用 Python 编写了一个使用多个脚本(模块)的项目。主脚本调用其他模块并从文件夹中读取一些文件以执行其功能。
我正在尝试将其打包以进行分发。我希望从命令行使它成为一个可运行的程序,这意味着,一旦用户下载并安装它,他们就可以这样调用程序:
$ python my_program -i arg1 -o arg2
或类似的。
我在网上找到的教程以可以导入的包的形式包装项目。
>> import my_program
>> my_program.run_stuff(arg1, arg2)
那不是我想要的。
解决方案
既然你写了“或类似的”,假设你想这样调用程序:
$ my_program -i arg1 -o arg2
这甚至更短。这也是我们如何称呼无处不在的 Python 工具,例如pip
. 并且有一个既定的程序可以为任何 Python 包定义一个“入口点”(众所周知)。
所有 Python 打包工具都允许这样做。如果我们愿意,我们可以使用经典的 Setuptools——这就是 Pip 所做的。或者使用 Poetry,一种更现代的选择。但使用Flit进行设置通常是最容易的。
在最简单的情况下,你的包my_program
只包含一个__init__.py
定义函数的文件:
def main():
print('Running my program...')
该函数通常会作用于sys.argv
. 该函数不必被调用main
,它可以是任何名称,也可以在包的任何其他模块中。
然后我们可以在项目的元数据中定义控制台脚本的入口点。pyproject.toml
Flit 从根文件夹中命名的配置文件中读取。所以存储库现在看起来像这样:
.
├── my_program
│ └── __init__.py
└── pyproject.toml
使用元数据的最新标准PEP 621将pyproject.toml
包含:
[project]
name = 'my_program'
version = '1.0.0'
description = 'Can be run in the console from anywhere.'
[project.scripts]
my_program = 'my_program:main'
[build-system]
requires = ['flit_core>=3.2,<4']
build-backend = 'flit_core.buildapi'
在[ project.scripts
] 部分中,我们将控制台命令映射my_program
到包main
的顶级名称空间中的函数my_program
。同样,它也可以是包中其他地方的任何其他功能。
现在我们打包项目:
$ flit build --format wheel
Copying package file(s) from my_program I-flit_core.wheel
Writing metadata files I-flit_core.wheel
Writing the record of files I-flit_core.wheel
Built wheel: dist\my_program-1.0.0-py2.py3-none-any.whl I-flit_core.wheel
这会将打包的“轮子”放在一个名为dist
. 我们可以将该.whl
文件上传到PyPI进行分发,或者立即使用 Pip 安装它:
$ pip install dist/my_program-1.0.0-py2.py3-none-any.whl
Processing .\dist\my_program-1.0.0-py2.py3-none-any.whl
Installing collected packages: my-program
Successfully installed my-program-1.0.0
现在我们可以像运行任何其他控制台应用程序一样运行该程序:
$ my_program
Running my program...
Pip 为我们所做的是,它在它自己的启动器旁边为我们的包创建了一个小型启动器。就像Flit一样。例如,在 Windows 上,现在有一个my_program.exe
内部 Python文件夹,就在和Scripts
旁边。pip.exe
flit.exe
推荐阅读
- javascript - 使用 Angular js(获取)从大型 API 动态呈现答案
- rest - Gin 错误恐慌:通配符路由与现有子节点冲突
- mongodb - Mongoose:用于级联删除的 deleteOne 中间件不起作用
- sql - SQLAlchemy/SQL:过滤表,然后加入查询
- ssh - SSH Windows 10,找出什么版本
- esb - Transformers 不能循环遍历列表元素
- multithreading - 不覆盖*标准输入*可防止多线程
- python - Flutter / Dart 没有从本地托管的烧瓶 api 返回值
- mysql - 获得最后评论文章的最佳查询是什么?
- html - 相对于图像定位元素