Python应用程序打包工具setuptools的使用(内含示例)
写完的Python项目或者Django应用,通过setuptools打包与分发,可以打包成whl文件,发布到PyPI(https://pypi.org/)上或者搭建PyPI私服,提供给企业内部使用或别的小伙伴使用,通过简单的命令pip install 安装即可使用。setuptools库的前身是distutils(一个python标准库),setuptools本身不是标准库,所以需要自行安装。
setuptools提供的主要的功能有:python库的打包分发依赖包安装与版本管理python环境限制生成脚本c/c++ 拓展利用EasyInstall自动查找、下载、安装、升级依赖包创建Python Eggs包含包目录内的数据文件自动包含包目录内的所有的包,而不用在setup.py中列举自动包含包内和发布有关的所有相关文件,而不用创建一个MANIFEST.in文件自动生成经过包装的脚本或Windows执行文件支持Pyrex,即在可以setup.py中列出.pyx文件,而最终用户无须安装Pyrex支持上传到PyPI可以部署开发模式,使项目在sys.path中用新命令或setup()参数扩展distutils,为多个项目发布/重用扩展在项目setup()中简单声明entry points,创建可以自动发现扩展的应用和框架
一、安装setuptools和wheel
pip install setuptools wheel
二、打包项目示例
项目结构
-lqz_books-lqz_books-__init__.py-apps-books-__init__.py-static-templates-asgi.py-db.sqlite3-manage.py-settings.py-urls.py-wsgi.pyREADME.mdMANIFEST.inrequirements.txtsetup.py
在项目根路径下编写setup.py 文件
from setuptools import setupdef readme():with open('README.md', encoding='utf-8') as f:content = f.read()return contentsetup(name = 'lqz_books', # 包名称version = '1.0.1', # 版本author = 'lqz', # 作者author_email = '306334678@qq.com', # 作者邮箱description='lqz_books demo', # 描述long_description=readme(), # 长文字描述long_description_content_type='text/markdown', # 长文描述的文本格式keywords='django', # 关键词url='https://gitee.com/liuqingzheng/lqz_books', # 项目主页license='Apache License 2.0', # 许可证# packages=find_packages() 能在你源目录下找到所有模块的特殊函数,必须是包结构,包下有__init__,文件夹不行# include_package_data=True 表示要打包非py文件,比如咱们的static,templates等【需要再MANIFEST.in中配置】,当为True时,将根据MANIFEST.in文件来打包分发库# package_data ,指定要打包的,除了py文件之外的文件# install_requires 当前项目的所有依赖)packagesinclude_package_data(其实就是MANIFEST.in文件)exclude_package_datapackage_datadata_files
包含的文件说明如下:
py_modules和packages 参数中所有 Python 源文件ext_modulesorlibraries 参数中提到的所有 C 源文件scripts 参数指定的脚本package_data和data_files 参数指定的所有文件setup.cfg和setup.py类似于readme的文件 如README、README.txt、 README.rst、README.mdMANIFEST.in 中指定的所有文件
MANIFEST.in语法规则
| 命令 | 描述 |
|---|---|
| include pat1 pat2 ... | 添加与任何列出的模式匹配的所有文件(文件必须作为相对于项目根目录的路径给出) |
| exclude pat1 pat2 ... | 删除与任何列出的模式匹配的所有文件(文件必须作为相对于项目根目录的路径给出) |
| recursive-include dir-pattern pat1 pat2 ... | 递归dir-pattern及其子文件夹,添加与任何列出的模式匹配的目录下的所有文件 |
| recursive-exclude dir-pattern pat1 pat2 ... | 递归dir-pattern及其子文件夹,删除与任何列出的模式匹配的目录下的所有文件 |
| global-include pat1 pat2 ... | 在源树中的任何位置添加与任何列出的模式匹配的所有文件 |
| global-exclude pat1 pat2 ... | 删除源树中与任何列出的模式匹配的所有文件 |
| graft dir-pattern | 添加匹配目录下的所有文件 dir-pattern |
| prune dir-pattern | 删除匹配目录下的所有文件 dir-pattern |
依赖包安装与版本管理
一个项目库可能会依赖于很多其他库,比如安装pandas,该库依赖于numpy。
针对依赖包安装与版本管理,setup函数提供了参数install_requires、 setup_requires、tests_require 、extras_require
# 表明当前模块依赖哪些包,若环境中没有,则会从pypi中自动下载安装install_requires=['docutils>=0.3'],#setup.py本身要依赖的包,这通常是为一些setuptools的插件准备的配置,这里列出的包,不会自动安装。setup_requires=['pbr'],# 仅在测试时需要使用的依赖,在正常发布的代码中是没有用的。# 在执行python setup.py test时,可以自动安装这三个库,确保测试的正常运行。tests_require=['pytest>=3.3.1','pytest-cov>=2.5.1',],# install_requires 在安装模块时会自动安装依赖包# 而 extras_require 不会,这里仅表示该模块会依赖这些包# 但是这些包通常不会使用到,只有当你深度使用模块时,才会用到,这里需要你手动安装extras_require={'PDF': ["ReportLab>=1.2", "RXP"],'reST': ["docutils>=0.3"],}
python环境限制
需要对python的版本进行限制时可以通过参数python_requires 来实现。
setup(python_requires='>=2.7, <=3')
生成脚本
有时候我们的库包含一些功能,每次都提供python XXX.py来运行不太方便,最好是把脚本放入系统环境path以命令行的形式来执行。setup函数提供了entry_points和scripts这两个参数来实现上述功能。它们的区别在于:entry_points是把python文件中的函数自动生成为可执行脚本,scripts是把.sh、.py等可执行脚本生成到系统path中。
from setuptools import setupsetup(…………# 把python中的函数自动生成为一个可执行的脚本# 如下:把fool.main文件中的main函数自动生成为一个可执行脚本,可以通过命令foo执行该脚本entry_points={'console_scripts': [ # key值为console_scripts'foo = foo.main:main' # 格式为'命令名 = 模块名:函数名']},# 将 bin/foo.sh 和 bar.py 脚本,生成到系统 PATH中# 执行 python setup.py install 后# 会生成 如 /usr/bin/foo.sh 和 如 /usr/bin/bar.pyscripts=['bin/foo.sh', 'bar.py'])
setuptools基础命令
build build everything needed to installbuild_py "build" pure Python modules (copy to build directory)build_ext build C/C++ extensions (compile/link to build directory)build_clib build C/C++ libraries used by Python extensionsbuild_scripts "build" scripts (copy and fixup #! line)clean clean up temporary files from 'build' commandinstall install everything from build directoryinstall_lib install all Python modules (extensions and pure Python)install_headers install C/C++ header filesinstall_scripts install scripts (Python or otherwise)install_data install data filessdist create a source distribution (tarball, zip file, etc.)register register the distribution with the Python package indexbdist create a built (binary) distributionbdist_dumb create a "dumb" built distributionbdist_rpm create an RPM distributionbdist_wininst create an executable installer for MS Windowsupload upload binary package to PyPI
自定义命令
继承完command类后,需要通过cmdclass参数告诉setuptools,该参数为一个字典,key为str命令名,value为继承于command类。
from setuptools import setupimport setuptools.command.build_ext as build_extclass BuildExtension(build_ext,object):…………setup( cmdclass={'build_ext': BuildExtension} )
参考资料
https://setuptools.pypa.io/en/latest/https://pythonhosted.org/an_example_pypi_project/setuptools.html




