Bob's Blog

Web开发、测试框架、自动化平台、APP开发、机器学习等

返回上页首页

打包自己的python代码



这里的打包不是指弄成可执行程序那样,而是将自己的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_目录路径, 还原了再内部发布使用。

下一篇:  在artifactory上传和安装python包
上一篇:  网页WCAG的检查以及工具尝试

共有2条评论

添加评论

Bo
2022年7月18日 18:37
@jackson 你应该可以试下pyinstaller
jackson
2022年7月18日 17:35
您好,问下如果是可执行文件的形式呢?该如何打包?