Python 包( 模块)分发
返回Python目录
before
centos 7.4 + python 3.6.8 + pip 9.0.3 + wheel 3.1.0
关于Python包管理工具的发展和使用本次共整理为三篇:
有失误或者引用链接不可用时,多多包涵,也欢迎留言斧正。
开始吧!
再来强调一些东西,想要制作whl文件,需要下载wheel模块支持:
pip install wheel pip install wheel==3.1.0 pip install https://pypi.doubanio.com/simple wheel==3.1.0
你应该考虑的规范
因为whl文件可以上传到PYPI
,所以,有些规范你要在制作whl文件的时候要注意,比如说要有:
- README:提供包的基本描述和使用方法。
- LICENSE:版权信息。
当然内部使用的时候,可以省略不写。
重中之重:setup.py文件
除此之外,包内要有一个重要的setup.py
文件,该文件主要使用setuptools的setup模块,提供打包所需要的基本信息。python依赖此脚本中的配置信息,将相关模块、静态文件,打包成一个完整的模块安装到site-packages文件。
所以,我们要重点研究下这个文件。
先上我的包目录结构:
[root@r zhaopeng]# pwd /home/zhaopeng [root@r zhaopeng]# tree . ├── setup.py └── wellcommon # 模块包 ├── com4gps.py ├── com.py ├── encrypt # 子目录,这也是一个重点 │ ├── helper4encrypt.py │ ├── __init__.py # 千万别忘了 __init__.py │ ├── py_apply.py │ ├── wzipfile.py │ └── zxzn_dll │ └── raspberrypi4B │ ├── libz.so │ ├── libz.so.1 │ ├── libz.so.1.2.11 │ └── libzxzn_dll.so ├── helper4file.py ├── helper4str.py ├── __init__.py # 千万别忘了 __init__.py ├── log.ini ├── log.py ├── MANIFEST ├── README.txt # 要是不上传什么PYPI,可以不写 └── wcv.py 4 directories, 19 files
注意setup.py
文件必须有且必须和包同级。
再来看setup.py
文件中一些重要的参数:
from setuptools import setup # 需要将那些包导入,注意,必须写包名,和包内的子目录,写法如下,普通的py文件无需写 packages = ["wellcommon", "wellcommon.encrypt"] # 如果有静态文件,这么导入即可 # file_data = [ # ("smart/static", ["smart/static/icon.svg", "smart/static/config.json"]), # ] # 第三方依赖 # requires = [ # "pandas>=0.23.4" # ] # 自动读取version信息,我这里没有,你可以参照 # about = {} # with open(os.path.join(here, 'smart', '__version__.py'), 'r', 'utf-8') as f: # exec(f.read(), about) # 自动读取readme # with open('README.txt', 'r', 'utf-8') as f: # readme = f.read() setup( # name=about["__title__"], # 包名称 name='wellcommon', # version=about["__version__"], # 包版本 version='1.0', # 包版本 # description=about["__description__"], # 包详细描述 # long_description=readme, # 长描述,通常是readme,打包到PiPy需要 # author=about["__author__"], # 作者名称 author='张开', # 作者名称 # author_email=about["__author_email__"], # 作者邮箱 author_email='xxxx@qq.com', # 作者邮箱 # url=about["__url__"], # 项目官网 url='https://www.cnblogs.com/Neeo/p/10864123.html', # 项目官网 packages=packages, # 项目需要的包 # data_files=file_data, # 打包时需要打包的数据文件,如图片,配置文件等 # include_package_data=True, # 是否需要导入静态数据文件 python_requires=">=3.0, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3*", # Python版本依赖 # install_requires=requires, # 第三方库依赖 zip_safe=False, # 此项需要,否则卸载时报windows error classifiers=[ # 程序的所属分类列表 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'Natural Language :: English', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy' ], )
上面的实例还是比较全的,setup函数中的重要参数:
- name:写成啥后续生成的报名就是啥。
- version:也会展示在生成whl名中。
- 作者信息之类的,看你自己了。
- packages:我认为非常重要的参数,如果你的包中有子目录,就要按照上述例子中的写法列出,不然容易出问题,当然要是包中都是
py
文件,可以不写该参数。 - 其他的什么url、requires就看具体情况而定了。
现在,基本配置倒是都完了,具体有没有问题,要打包的时候才知道。
制作过程
setup.py
文件写的有没有什么问题,有问题的会在给你提示处理来的,没有问题就不报错,也没提示,如下,就是没有问题的。[root@r zhaopeng]# python3 setup.py check running check [root@r zhaopeng]#
使用check
命令来检查,发现没有提示和报错,往下走。
[root@r zhaopeng]# pwd /home/zhaopeng [root@r zhaopeng]# python3 setup.py bdist_wheel running bdist_wheel running build running build_py creating build creating build/lib creating build/lib/wellcommon copying wellcommon/wcv.py -> build/lib/wellcommon copying wellcommon/log.py -> build/lib/wellcommon copying wellcommon/com4gps.py -> build/lib/wellcommon copying wellcommon/__init__.py -> build/lib/wellcommon copying wellcommon/helper4file.py -> build/lib/wellcommon copying wellcommon/com.py -> build/lib/wellcommon copying wellcommon/helper4str.py -> build/lib/wellcommon creating build/lib/wellcommon/encrypt copying wellcommon/encrypt/wzipfile.py -> build/lib/wellcommon/encrypt copying wellcommon/encrypt/py_apply.py -> build/lib/wellcommon/encrypt copying wellcommon/encrypt/__init__.py -> build/lib/wellcommon/encrypt copying wellcommon/encrypt/helper4encrypt.py -> build/lib/wellcommon/encrypt installing to build/bdist.linux-x86_64/wheel running install running install_lib creating build/bdist.linux-x86_64 creating build/bdist.linux-x86_64/wheel creating build/bdist.linux-x86_64/wheel/wellcommon creating build/bdist.linux-x86_64/wheel/wellcommon/encrypt copying build/lib/wellcommon/encrypt/wzipfile.py -> build/bdist.linux-x86_64/wheel/wellcommon/encrypt copying build/lib/wellcommon/encrypt/py_apply.py -> build/bdist.linux-x86_64/wheel/wellcommon/encrypt copying build/lib/wellcommon/encrypt/__init__.py -> build/bdist.linux-x86_64/wheel/wellcommon/encrypt copying build/lib/wellcommon/encrypt/helper4encrypt.py -> build/bdist.linux-x86_64/wheel/wellcommon/encrypt copying build/lib/wellcommon/wcv.py -> build/bdist.linux-x86_64/wheel/wellcommon copying build/lib/wellcommon/log.py -> build/bdist.linux-x86_64/wheel/wellcommon copying build/lib/wellcommon/com4gps.py -> build/bdist.linux-x86_64/wheel/wellcommon copying build/lib/wellcommon/__init__.py -> build/bdist.linux-x86_64/wheel/wellcommon copying build/lib/wellcommon/helper4file.py -> build/bdist.linux-x86_64/wheel/wellcommon copying build/lib/wellcommon/com.py -> build/bdist.linux-x86_64/wheel/wellcommon copying build/lib/wellcommon/helper4str.py -> build/bdist.linux-x86_64/wheel/wellcommon running install_egg_info running egg_info creating wellcommon.egg-info writing wellcommon.egg-info/PKG-INFO writing dependency_links to wellcommon.egg-info/dependency_links.txt writing top-level names to wellcommon.egg-info/top_level.txt writing manifest file 'wellcommon.egg-info/SOURCES.txt' reading manifest file 'wellcommon.egg-info/SOURCES.txt' writing manifest file 'wellcommon.egg-info/SOURCES.txt' Copying wellcommon.egg-info to build/bdist.linux-x86_64/wheel/wellcommon-1.0-py3.6.egg-info running install_scripts creating build/bdist.linux-x86_64/wheel/wellcommon-1.0.dist-info/WHEEL creating 'dist/wellcommon-1.0-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it adding 'wellcommon/__init__.py' adding 'wellcommon/com.py' adding 'wellcommon/com4gps.py' adding 'wellcommon/helper4file.py' adding 'wellcommon/helper4str.py' adding 'wellcommon/log.py' adding 'wellcommon/wcv.py' adding 'wellcommon/encrypt/__init__.py' adding 'wellcommon/encrypt/helper4encrypt.py' adding 'wellcommon/encrypt/py_apply.py' adding 'wellcommon/encrypt/wzipfile.py' adding 'wellcommon-1.0.dist-info/METADATA' adding 'wellcommon-1.0.dist-info/WHEEL' adding 'wellcommon-1.0.dist-info/top_level.txt' adding 'wellcommon-1.0.dist-info/RECORD' removing build/bdist.linux-x86_64/wheel
python3 setup.py bdist_wheel
命令是直接生成了whl文件,我们后面再说别的命令也能办同样的事情。
经过一长串的输出之后,我们来看看有没有打包成功。
[root@r zhaopeng]# pwd /home/zhaopeng [root@r zhaopeng]# ls build dist setup.py wellcommon wellcommon.egg-info
当打包命令执行后,会在setup.py
文件的同级目录中生成3个文件(夹)build、dist、wellcommon.egg-info
,我们只需要关注dist
目录即可。让我们cd进去看看都是啥东西:
[root@r zhaopeng]# ls dist/ wellcommon-1.0-py3-none-any.whl
没错,wellcommon-1.0-py3-none-any.whl
就是我们想要的东西,你把这个文件拷贝到任意python环境使用pip
命令安装即可。
pip install wellcommon-1.0-py3-none-any.whl
此时,这个包就安装在了你Python的安装目录中的Lib/site-packages/
目录下。
完事。
制作tar包
借着这个机会,就多说点,我们从PYPI
上面搜模块,在下载时,通常会给你两个选项让你选择:
如上图,whl格式目前被认为是Python二进制包的标准格式,下载的到本地需要使用pip install xxx.whl
安装;而tar包则是源码文件,你下载本地解压后就可以看到源码。
那么我们接下来就来聊聊如何制作tar包,然后再制作whl文件。这个跟上面的不冲突,如果你只想要whl文件,用刚才的命令即可:
python setup.py check # 检查setup.py文件是否有问题 python setup.py bdist_wheel # 直接生成whl文件
但是,如果你想要tar包,然后还要whl文件,则需要使用下面的命令:
python setup.py check # 检查setup.py文件是否有问题 python setup.py sdist # 主要生成dist文件 pip wheel --wheel-dir=/文件保存的目录 /setup.py文件所在工程目录 # wheel 需要单独下载,pip install wheel
来看这几个命令怎么玩的。
[root@r zhaopeng]# pwd /home/zhaopeng [root@r zhaopeng]# ls setup.py wellcommon
此时,再当前目录下,只有制作好的setup.py
和源码包wellcommon
。
setup.py
文件。[root@r zhaopeng]# pwd /home/zhaopeng [root@r zhaopeng]# python3 setup.py check running check [root@r zhaopeng]#
还是刚才的setup.py
文件,肯定没问题!
[root@r zhaopeng]# pwd /home/zhaopeng [root@r zhaopeng]# python3 setup.py sdist running sdist running egg_info creating wellcommon.egg-info writing wellcommon.egg-info/PKG-INFO writing dependency_links to wellcommon.egg-info/dependency_links.txt writing top-level names to wellcommon.egg-info/top_level.txt writing manifest file 'wellcommon.egg-info/SOURCES.txt' reading manifest file 'wellcommon.egg-info/SOURCES.txt' writing manifest file 'wellcommon.egg-info/SOURCES.txt' warning: sdist: standard file not found: should have one of README, README.rst, README.txt, README.md running check creating wellcommon-1.0 creating wellcommon-1.0/wellcommon creating wellcommon-1.0/wellcommon.egg-info creating wellcommon-1.0/wellcommon/encrypt copying files to wellcommon-1.0... copying setup.py -> wellcommon-1.0 copying wellcommon/__init__.py -> wellcommon-1.0/wellcommon copying wellcommon/com.py -> wellcommon-1.0/wellcommon copying wellcommon/com4gps.py -> wellcommon-1.0/wellcommon copying wellcommon/helper4file.py -> wellcommon-1.0/wellcommon copying wellcommon/helper4str.py -> wellcommon-1.0/wellcommon copying wellcommon/log.py -> wellcommon-1.0/wellcommon copying wellcommon/wcv.py -> wellcommon-1.0/wellcommon copying wellcommon.egg-info/PKG-INFO -> wellcommon-1.0/wellcommon.egg-info copying wellcommon.egg-info/SOURCES.txt -> wellcommon-1.0/wellcommon.egg-info copying wellcommon.egg-info/dependency_links.txt -> wellcommon-1.0/wellcommon.egg-info copying wellcommon.egg-info/not-zip-safe -> wellcommon-1.0/wellcommon.egg-info copying wellcommon.egg-info/top_level.txt -> wellcommon-1.0/wellcommon.egg-info copying wellcommon/encrypt/__init__.py -> wellcommon-1.0/wellcommon/encrypt copying wellcommon/encrypt/helper4encrypt.py -> wellcommon-1.0/wellcommon/encrypt copying wellcommon/encrypt/py_apply.py -> wellcommon-1.0/wellcommon/encrypt copying wellcommon/encrypt/wzipfile.py -> wellcommon-1.0/wellcommon/encrypt Writing wellcommon-1.0/setup.cfg creating dist Creating tar archive removing 'wellcommon-1.0' (and everything under it)
有些warning
提示无伤大雅,主要看有没有生成文件。
[root@r zhaopeng]# pwd /home/zhaopeng [root@r zhaopeng]# ls dist setup.py wellcommon wellcommon.egg-info
python setup.py sdist
命令新生成了dist
和wellcommon.egg-info
,此时,dist
目录内就有了tar包。
[root@r zhaopeng]# pwd /home/zhaopeng [root@r zhaopeng]# ls dist/ wellcommon-1.0.tar.gz
4. 有了tar包,再来看怎么生成whl文件。
[root@r zhaopeng]# pwd /home/zhaopeng [root@r zhaopeng]# pip3 wheel --wheel-dir=/home/zhaopeng/ /home/zhaopeng/ Processing /home/zhaopeng Building wheels for collected packages: wellcommon Running setup.py bdist_wheel for wellcommon ... done Stored in directory: /home/zhaopeng Successfully built wellcommon
看到了Successfully
就知道命令执行成功。
现在解释下pip3 wheel --wheel-dir=/home/zhaopeng/ /home/zhaopeng/
命令中的两个目录都是啥意思:
--wheel-dir=/home/zhaopeng/
,--wheel-dir
后跟的目录是生成的whl文件保存的目录。/home/zhaopeng/
,空格后的这个目录是这条命令执行的工程目录,pip3 wheel
命令会找setup.py
文件,所以,工程目录就是setup.py
文件所在的目录。
现在,在setup.py
文件的同级目录内就有了whl文件。
[root@r zhaopeng]# pwd /home/zhaopeng [root@r zhaopeng]# ls dist setup.py wellcommon wellcommon-1.0-py3-none-any.whl wellcommon.egg-info
OK,现在whl文件也有了,完事。
小结
整篇博客整理下来,也对这几个命令有了更多的了解:
python setup.py check # 用来校验setup.py文件的正确性 python setup.py sdist # 主要生成dist文件 python setup.py bdist_wheel pip wheel --wheel-dir=/文件保存的目录 /setup.py文件所在工程目录
python setup.py check
这个就不用说了,无论是制作tar包还是whl文件都要先检查。
现在来看别的命令:
python setup.py bdist_wheel pip wheel --wheel-dir=/文件保存的目录 /setup.py文件所在工程目录
这两个命令都可以单独使用,都是用来生成whl文件的,区别是:
bdist_wheel
命令是编译生成,会产生build
、dist
、wellcommon.egg-info
三个文件(夹),而whl文件则在dist
目录内。wheel
命令则更直接,不会产生中间文件,一步到位生成whl文件。
而python setup.py sdist
则是用来打包源码包的,该命令会生成dist
目录(而源码包也在该目录内)、wellcommon.egg-info
文件。
说到这,暂时没啥补充的了。
see also:
Python 第三方包制作教程 | python whl是什么文件 | 将python包发布到PyPI和制作whl文件 | 打包Python项目