distutils 简介

distutils 是标准库中负责建立 Python 第三方库的安装器,使用它能够进行 Python 模块的安装和发布。distutils 对于简单的分发很有用,但功能缺少。

setuptools 简介

setuptools 是 distutils 增强版,不包括在标准库中。其扩展了很多功能,能够帮助开发者更好的创建和分发 Python 包。大部分 Python 用户都会使用更先进的 setuptools 模块。

特性文件

setup.py、MANIFEST.in、setup.cfg

第一个安装文件

假设我们的项目名为”setup-demo”,包名为”myapp”,目录结构如下:

setup-demo/├ setup.py        # 安装文件└ myapp/          # 源代码├ __init__.py...

一个最基本的”setup.py”文件如下:

#coding:utf8
from setuptools import setup
setup(name='MyApp',        # 项目名version='1.0',       # 版本号packages=['myapp']   # 包括在安装包内的Python包
)

setup.py命令

help

查看所有支持的命令:

python setup.py --help-commands

build

构建安装时所需的所有内容:

python setup.py build

install

安装包到系统环境中。该命令会将当前项目安装到当前Python环境的”site-packages”目录下,这样其他项目就可以像导入标准库一样导入该项目的代码了。

python setup.py install

develop

开发方式安装包

如果项目在开发过程中会频繁变更,每次安装还需要先将原来的版本卸掉,会很麻烦。使用”develop”开发方式安装的话,项目代码不会真的被拷贝到本地Python环境的”site-packages”目录下,而是在”site-packages”目录里创建一个指向当前项目位置的链接。这样如果当前位置的源码被改动,就会马上反映到”site-packages”里。

python setup.py develop

register、upload

用于包的上传发布

python setup.py register
# 发布源码包
python setup.py sdist upload

以下为python的打包命令:

build_ext

构建扩展,如用 C/C++, Cython 等编写的扩展,在调试时通常加 --inplace 参数,表示原地编译,即生成的扩展与源文件在同样的位置。

python setup.py build_ext

sdist

构建源码分发包。该命令会在当前目录下的”dist”目录内创建一个压缩包,默认在 Windows 下为 zip 格式,Linux 下为 tag.gz 格式 ,也可以通过指定--formats参数指定压缩包格式。

执行 sdist 命令时,默认会被打包的文件:

  • 所有 py_modules 或 packages 指定的源码文件
  • 所有 ext_modules 指定的文件
  • 所有 package_data 或 data_files 指定的文件
  • 所有 scripts 指定的脚本文件
  • README、README.txt、setup.py 和 setup.cfg文件

该命令构建的包主要用于发布,例如上传到 pypi 上。

python setup.py sdist

bdist

构建一个二进制的分发包。

python setup.py bdist

bdist_egg

构建一个 egg 分发包,经常用来替代基于 bdist 生成的模式。该命令会在当前目录下的”dist”目录内创建一个”egg”文件,名为”MyApp-1.0-py2.7.egg”。文件名格式就是”项目名-版本号-Python版本.egg”。同时你会注意到,当前目录多了”build”和”MyApp.egg-info”子目录来存放打包的中间结果。

python setup.py bdist_egg

bdist_wheel

构建一个 wheel 分发包,egg 包是过时的,whl 包是新的标准。同上面类似,只是打成的包的后缀是.whl 。

python setup.py bdist_wheel

引入非Python文件

上例中,我们只会将”myapp”包下的源码打包,如果想引入静态文件,如JS、CSS、图片等,怎么做?

答:在项目根目录下添加一个”MANIFEST.in”文件夹。假设我们把所有静态文件都放在”static”子目录下,现在的项目结构如下:

 setup-demo/├ setup.py        # 安装文件├ MANIFEST.in     # 清单文件└ myapp/          # 源代码├ static/     # 静态文件目录├ __init__.py...

我们在清单文件”MANIFEST.in”中,列出想要在包内引入的目录路径:

recursive-include myapp/static *
recursive-include myapp/xxx *

recursive-include表明包含子目录。

在”setup.py”中将include_package_data参数设为True

#coding:utf8
from setuptools import setup
setup(name='MyApp',        # 项目名version='1.0',# 版本号packages=['myapp'],  # 包括在安装包内的Python包include_package_data=True   # 启用清单文件MANIFEST.in
)

如果你想排除一部分文件,可以在”setup.py”中使用exclude_package_date参数:

setup(...include_package_data=True, # 启用清单文件MANIFEST.inexclude_package_date={'':['.gitignore']}
)

依赖管理

我们的项目会依赖其他Python模块,如何在setup.py中管理这些依赖呢?

答:修改”setup.py”文件,加入install_requires参数:

#coding:utf8
from setuptools import setup
setup(name='MyApp',        # 项目名version='1.0',# 版本号packages=['myapp'],  # 包括在安装包内的Python包include_package_data=True,   # 启用清单文件MANIFEST.inexclude_package_date={'':['.gitignore']},install_requires=[   # 依赖列表'Flask>=0.10','Flask-SQLAlchemy>=1.5,<=2.1']
)

上面的代码中,我们声明了应用依赖Flask 0.10及以上版本,和Flask-SQLAlchemy 1.5及以上、2.1及以下版本。setuptools会先检查本地有没有符合要求的依赖包,如果没有的话,就会从PyPI中获得一个符合条件的最新的包安装到本地。

可以通过dependency_links指定依赖包下载路径。install_requires中的包在安装时会先去PyPI下载并安装,如果包在PyPI中找不到,则会从dependency_links标识的URL中获取:

setup(...install_requires=[   # 依赖列表'Flask>=0.10','Flask-SQLAlchemy>=1.5,<=2.1'],dependency_links=[   # 依赖包下载路径'http://example.com/dependency.tar.gz']
)

路径应指向一个”egg”包或”tar.gz”包,也可以是个包含下载地址(一个”egg”包或”tar.gz”包)的页面。

PS:现在python的第三方依赖一般写在requirements.txt 文件中,然后用pip工具下载。关于他们的不同,可以参考我的博客中requirements.txt VS install_requires 这一小节。

自动搜索Python包

packages=['myapp'] :将Python包”myapp”下的源码打包。

之前我们在”setup.py”中指定了packages=['myapp'],说明将Python包”myapp”下的源码打包。但是如果我们的应用很大,逐一列举需要打包的源码包会很麻烦,这时就需要用到setuptools提供的find_packages()方法来自动搜索可以引入的Python包。

packages=find_packages()自动搜索可以引入的Python包,它默认在与 setup.py 文件同一目录下搜索各个含有 __init__.py 的目录做为要添加的包。

#coding:utf8
from setuptools import setup, find_packages
setup(name='MyApp',              # 应用名version='1.0',             # 版本号packages=find_packages(),  # 包括在安装包内的Python包include_package_data=True,  # 启用清单文件MANIFEST.inexclude_package_date={'':['.gitignore']},install_requires=[         # 依赖列表'Flask>=0.10','Flask-SQLAlchemy>=1.5,<=2.1']
)

find_packages()方法可以限定你要搜索的路径,比如使用find_packages('src')就表明只在”src”子目录下搜索所有的Python包。

发布包

setuptools 支持使用 setup.py upload 上传包文件到 PyPI,但只支持 HTTP 而被新的 twine 取代。

方式一:使用setup.py upload发布

(1)配置.pypirc配置文件。.pypirc配置文件在用户根目录下的:~/.pypirc ,也可以通过修改setup.py文件,替换registerupload命令的_get_rc_file方法来自定义文件路径(参考https://blog.csdn.net/weixin_38384296/article/details/112500564 .pypirc配置文件一节)

[distutils]
index-servers =pypiprivate-repository[pypi]
username = __token__
password = <PyPI token>[private-repository]
repository = <private-repository URL>
username = <private-repository username>
password = <private-repository password>

(2)接着注册项目

python setup.py register

(3)构建源码包发布:

# 发布源码包
python setup.py sdist upload# 同时发布源码包和 whl 二进制包
python setup.py sdist bdist_wheel upload

方式二:使用twine发布

官方提供了 twine 工具专门用来与 PyPI 交互,twine支持上传任何包装格式,其包含三个子命令check, register, upload,且同样支持从.pypirc中读取配置。上传包时,直接用 upload 命令:

# 构建包
python setup.py sdist bdist_wheel
# 通过-r指定上传到哪个仓库(https://stackoverflow.com/questions/57935191/twine-is-asking-for-my-password-each-time-how-to-use-the-pypirc)
twine upload -r private-repository dist/*
#上传到指定仓库,还可以通过-u指定用户名,-p指定密码
twine upload --repository-url 仓库地址 -u 用户名 -p 密码 dist/*

使用twine upload发布到http开头的私有库时,有可能会报证书校验失败的错误(certificate verify failed)。这种情况下,可以使用以下命令禁用SSL验证(https://stackoverflow.com/questions/67795829/how-to-disable-ssl-certificate-verification-in-twine):

export CURL_CA_BUNDLE=""

参考

http://www.bjhee.com/setuptools.html
https://packaging.python.org/specifications/pypirc/
https://twine.readthedocs.io/en/latest/#twine-upload

setuptools简介相关推荐

  1. Python打包分发工具setuptools简介

    Python打包分发工具setuptools 通过这个工具,可以打包安装插件,并且还可以发布到PyPI上面,具体参考: 1.http://python.jobbole.com/87240/ 2.htt ...

  2. python项目使用setuptools和rpmbuild构建rpm包

    python项目使用setuptools和rpmbuild构建rpm包 文章目录 python项目使用setuptools和rpmbuild构建rpm包 一.setuptools 二.使用rpmbui ...

  3. python自己写包_Python将自己写的模块进行打包

    将项目打包成模块的想法来自于flask文档教程,这不是在PyCon上和阿明合了照嘛,这不得多看看人家的东西.有兴趣的可以看看文档的项目可安装化部分,作者将flask项目打包成一个包,使其可以再任何地方 ...

  4. python3项目-python3项目

    广告关闭 2017年12月,云+社区对外发布,从最开始的技术博客到现在拥有多个社区产品.未来,我们一起乘风破浪,创造无限可能. 服务器是腾讯云的,系统是ubuntu18.04,自带python2和py ...

  5. python项目归纳总结-python项目总结

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 概览 这里主要收集python项目的打包.发布和部署的常用方法,只是入门级别,深 ...

  6. python项目-python完整项目

    广告关闭 腾讯云双11爆品提前享,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高满返5000元! 一个完整的python项目需要具备什么? 1. 需求功能的实现: 实现思路+现有框 ...

  7. python 点点滴滴

    1. python 查看字符编码 string = "helloworld" import chardet print "编码: ", chardet.dete ...

  8. 【Python】三、代码组织架构

    0 序 我虽然没参加过比较大型的多人协作项目,但也独立开发过上万行的C++.Python项目,所以多少有些工程经验吧,在此不辞领教,分享下如何能开发一个结构清晰,代码易维护,鲁棒性强,功能扩展性强的工 ...

  9. Python 库打包分发(setup.py 编写)

    Python 有非常丰富的第三方库可以使用,很多开发者会向 pypi 上提交自己的 Python 包.要想向 pypi 包仓库提交自己开发的包,首先要将自己的代码打包,才能上传分发. distutil ...

最新文章

  1. kafka的topic和分区策略——log entry和消息id索引文件
  2. 导入torchvision出现:AttributeError: module ‘torch.jit‘ has no attribute ‘unused‘错误
  3. 【设计模式】软件设计七大原则 ( 接口隔离原则 | 代码示例 )
  4. java自定义日志级别_自定义log4j日志级别
  5. SQL SERVER中直接循环写入数据
  6. 牛客题霸 NC23 划分链表
  7. [Python人工智能] 二十三.基于机器学习和TFIDF的情感分类(含详细的NLP数据清洗)
  8. 创建java类并实例化类对象
  9. python微信语音转发方法_语音转发方法与流程
  10. mysql经纬度与度分秒转换
  11. 每日一记—蓝牙模块应用(一)
  12. 考研英语-旧题高频词(齐雪妮老师)-2020-02-27,03-05,03-12,03-19
  13. 坎德拉、流明、勒克斯之间的关系
  14. 1.计算机领域的安全世界观
  15. ZOJ3549 Little Keng(快速幂)
  16. 实验吧-简单的登录题——WriteUp再研究
  17. background图片叠加_css在图片上叠加层(其他图标)
  18. JVM中类加载的时机
  19. macOS安装软件./configuredmake
  20. AI顶级期刊 IEEE T-PAMI 2020最新论文解读 | Deep Partial Multi-View Learning

热门文章

  1. Matlab之图像变换技术(十二)
  2. 一个开发周期为6个月的中小型软件开发项目成本预算大致表
  3. TS文件用vlc播放,seek灰屏问题研究
  4. AMD双核补丁吐血之作6个补丁
  5. 博科交换机java版本_博科交换机安装与维护手册.doc
  6. 希捷推7200.12硬盘单碟容量再提升500G
  7. 便宜寄快递攻略,3.5R寄全国
  8. 数值策划的自我修养(二):用VBA批量获取指定目录下文件的名字
  9. 太太太好用了!12款论文润色神器,SCI、EI论文写作必看
  10. 【andriod】 设备APP连接云端平台的各种细节部署和操作