打包自己的python代码
2021年12月1日 - 由Bo 2 评论 1455 阅读
这里的打包不是指弄成可执行程序那样,而是将自己的python代码处理为可以安装的包,并可以上传pypi或者内部的artifactory,用于在requirements中定义并安装对应的版本。
首先安装setuptools和wheel
pip install setuptools wheel
接着需要定义setup.py。先看看样例的目录结构, demo_package就是需要打包的代码集:
- code folder
- demo_package
- any code here
- setup.py
- README
- LICENSE
- requirements.txt
setup.py的内容可以是如下:
from setuptools import setup, find_packages
def find_requires():
requires = []
with open("./requirements.txt", "r") as f:
packages = f.read().strip().split("\n")
for pkg in packages:
requires.append(pkg)
return requires
setup(
name="demo_package",
version="1.0.0",
author="bo",
author_email="bobjiang4321@gmail.com",
description="demo show how to package python code",
license="MIT",
url="https://github.com/demo/package",
packages=find_packages(),
package_data={"":["*.yaml", "*.py"]},
classifiers=[
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Operating System :: OS Independent"
],
python_requires=">=3.6",
install_requires=find_requires()
)
这些参数有的可以不写,但加上这些比较清楚,它们的意思是:
name为用于指定安装的包的名字,注意保持唯一性;
version是包的具体的版本号;
author和email是指作者的名字和邮箱;
description是一个简单的描述,如果有特殊信息比如readme的内容,还可以用long_description来描述;
license是版权类型;
url是项目的地址;
packages是指需要的文件,这里用了setuptools自带的find_packages来自动查找文件;
当包含了非py的文件,则需要定义package_data,比如这里指明了还需要加上其中的yaml文件;
classifier是附加说明,比如这里的样例是指需要用python3,协议是MIT,独立于OS;
python_requires是指细化的python版本;
install_requires是指当前包需要安装的其他包,这里就是将当前需要打包项目的requirements给添加了进去;
接着运行命令来产生包文件:
python setup.py sdist bdist_wheel
运行后会发现在当前目录下多出了三个文件夹:build,dist,demo_package.egg-info。在其中dist的文件夹里,tar.gz的文件则是代码的压缩文件,而另一个whl就是我们想要的用来安装的包文件。
因为包文件还在本地,我们用指明路径的方式来安装:
pip install /folder_path/demo_package-1.0.0-py3-none-any.whl
安装成功后就可以试试import啦。
这里有人会注意到这个whl文件里有个none和any,这是因为没有指定。whl的文件名格式是:{distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform tag}.whl。build tag先不管,而abi tag则对应着none,platform tag对应着any。如果需要加上这两个tag,可以在setup.py中加一个参数cmdclass,上面的setup.py可以用下面来代替:
from setuptools import setup, find_packages
def find_requires():
requires = []
with open("./requirements.txt", "r") as f:
packages = f.read().strip().split("\n")
for pkg in packages:
requires.append(pkg)
return requires
try:
from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
class bdist_wheel(_bdist_wheel):
def finalize_options(self):
_bdist_wheel.finalize_options(self)
self.root_is_pure = False
except ImportError:
bdist_wheel = None
setup(
name="demo_package",
version="1.0.0",
author="bo",
author_email="bobjiang4321@gmail.com",
description="demo show how to package python code",
license="MIT",
url="https://github.com/demo/package",
packages=find_packages(),
package_data={"":["*.yaml", "*.py"]},
classifiers=[
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Operating System :: OS Independent"
],
python_requires=">=3.6",
install_requires=find_requires(),
cmdclass={'bdist_wheel': bdist_wheel}
)
这样再次运行python setup.py sdist bdist_wheel后便可看到新的whl文件名中带有了额外的tag: demo_package-1.0.0-cp38-cp38-macosx_10_14_x86_64.whl.
另外如果需要修改其他来源的whl包然后再重新发布,比如下载了opencv,使用wheel unpack opencv.whl,在新出现的目录中修改文件内容,然后用wheel pack opencv_目录路径, 还原了再内部发布使用。
共有2条评论
添加评论
Bo
2022年7月18日 18:37@jackson 你应该可以试下pyinstaller
jackson
2022年7月18日 17:35您好,问下如果是可执行文件的形式呢?该如何打包?