Python setup.py 安装包详解

发布时间: 更新时间: 总字数:2743 阅读时间:6m 作者: 分享 复制网址

Python 安装包在不同系统有不同的安装方式,其底层依赖 setup.py 实现,本文详细介绍 setuptools 的实现原理和使用指南。

打包工具介绍

  • distutils: Python 官方开发的标准库distribute utils,Python 打包工具的始祖,核心配置文件 setup.cfg/setup.py
  • setuptools: distutils 的升级版本,主流实现
  • distribute: 是 setuptools 的分支版本,关系比较密切。

本文重点介绍 setuptools 的使用。

安装

pip2 install setuptools
# or
pip3 install setuptools
# or
pip3 install setuptools==39.2.0

help

python-setup_py--help
$ python3 setup.py --help-commands
Standard commands:
  build             build everything needed to install
  build_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 extensions
  build_scripts     "build" scripts (copy and fixup #! line)
  clean             clean up temporary files from 'build' command
  install           install everything from build directory
  install_lib       install all Python modules (extensions and pure Python)
  install_headers   install C/C++ header files
  install_scripts   install scripts (Python or otherwise)
  install_data      install data files
  sdist             create a source distribution (tarball, zip file, etc.)
  register          register the distribution with the Python package index
  bdist             create a built (binary) distribution
  bdist_dumb        create a "dumb" built distribution
  bdist_rpm         create an RPM distribution
  bdist_wininst     create an executable installer for MS Windows
  check             perform some checks on the package
  upload            upload binary package to PyPI

Extra commands:
  egg_info          create a distribution's .egg-info directory
  develop           install package in 'development mode'
  rpm_version       Output the rpm *compatible* version string of this package
  deb_version       Output the deb *compatible* version string of this package
  alias             define a shortcut to invoke one or more commands
  bdist_egg         create an "egg" distribution
  dist_info         create a .dist-info directory
  easy_install      Find/get/install Python packages
  install_egg_info  Install an .egg-info directory for the package
  rotate            delete older distributions, keeping N newest files
  saveopts          save supplied options to setup.cfg or other config file
  setopt            set an option in setup.cfg or another config file
  test              run unit tests after in-place build
  upload_docs       Upload documentation to PyPI

usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
   or: setup.py --help [cmd1 cmd2 ...]
   or: setup.py --help-commands
   or: setup.py cmd --help

常用命令

# install everything from build directory
python3 setup.py install

# create a source distribution
python3 setup.py sdist

# create an RPM distribution
python3 setup.py bdist_rpm

# create an "egg" distribution
python3 setup.py bdist_egg

# create an executable installer for MS Windows, 必须在 Windows 上执行
python3 setup.py bdist_wininst

包格式

  • 源码包:以压缩格式存在,一般为 tar.gz,安装时需要根据不同平台编译。包一般比较大。
  • 二进制包:已经编译,一般以 eggswheels/whl 形式存在,安装速度比源码快。
    • egg(.egg): 由 setuptools 在 2004 年引入,本质上是一个包含了项目代码以及元数据(一个名为egg-info的子目录)的zip压缩包
    • wheels(.whl): 由 PEP427 在 2012 年定义,Wheel 格式的包中包含一个名为 .dist-info 的子目录,目标是替代 egg

区别

Wheel 和 Egg 的主要区别:

  • Egg 既是一种分发格式,也是一种运行时安装的格式,并且是可以被直接 import
  • Egg 格式的包需要使用 easy_install 进行安装,
  • Wheel 有一个官方的 PEP427 来定义,而 Egg 没有 PEP 定义
  • Wheel 是一种分发格式,即打包格式。
  • Wheel 文件不会包含 .pyc 文件
  • Wheel 使用和 PEP376 兼容的 .dist-info 目录,而 Egg 使用 .egg-info 目录
  • Wheel 有着更丰富的命名规则
  • Wheel 是有版本的。每个 Wheel 文件都包含 wheel 规范的版本和打包的实现
  • Wheel 在内部被 sysconfig path type 管理,因此转向其他格式也更容易
  • Wheel 可以使用 pip 安装(tgz的也可以)
  • .whl 文件有一点与 .egg 文件相似:实际上它们都是 .zip 文件。可以将 .whl 文件名扩展改为 .zip,就可以使用 zip 应用程序打开它

配置

Pecan 使用介绍 为例

setup.py

# -*- coding: utf-8 -*-
try:
    from setuptools import setup, find_packages
except ImportError:
    from ez_setup import use_setuptools
    use_setuptools()
    from setuptools import setup, find_packages

setup(
    name='test_pecan',
    version='0.1',
    description='',
    author='',
    author_email='',
    install_requires=[
        "pecan",
    ],
    test_suite='test_pecan',
    zip_safe=False,
    include_package_data=True,
    packages=find_packages(exclude=['ez_setup'])
)

setup 函数参数:

  • classifiers: 包的分类信息
  • packages: 告诉Distutils需要处理那些包(包含__init__.py的文件夹)
  • package_dir: 告诉Distutils哪些目录下的文件被映射到哪个源码包。一个例子:package_dir = {'': 'lib'},表示 root package 中的模块都在lib目录中
  • ext_modules: 是一个包含Extension实例的列表,Extension的定义也有一些参数
  • ext_package: 定义extension的相对路径
  • requires: 定义依赖哪些模块
  • provides: 定义可以为哪些模块提供依赖
  • scripts: 指定python源码文件,可以从命令行执行。在安装时指定–install-script
  • package_data: 通常包含与包实现相关的一些数据文件或类似于readme的文件。如果没有提供模板,会被添加到MANIFEST文件中
  • exclude_package_data 不打包的文件
  • data_files: 静态文件,如配置文件、service文件等
  • cmdclass={'my_command': XXXCommand} 用来指定用户自定义的命令类
    • XXXCommand 用户自定义命令类,继承自 distutils.core.Command 类,用来执行一些特定的任务
    • 当执行 python setup.py my_command 时,将会调用 XXXCommand 类的 run() 方法来执行任务
setup(...,
	data_files=[
		('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),
		('config', ['cfg/data.cfg']),
		('/etc/init.d', ['init-script'])]
	)

规定了哪些文件被安装到哪些目录中。如果目录名是相对路径,则是相对于 sys.prefixsys.exec_prefix 的路径

setup.cfg

[nosetests]
match=^test
where=test_pecan
nocapture=1
cover-package=test_pecan
cover-erase=1

MANIFEST.in

MANIFEST.in 用来控制文件的分发,如下例:

include *.txt
recursive-include examples *.txt *.py
prune examples/sample?/build

作用如下:

  • 第一行:所有根目录下的以 txt 为后缀名的文件,都会分发
  • 第二行:根目录下的 examples 目录 和 txt、py 文件都会分发
  • 第三行:路径匹配上 examples/sample?/build 不会分发

MANIFEST.insetup.py 同级的目录下,setuptools 时会自动读取该文件

PBR

pbrsetuptools 的辅助工具,最初由 OpenStack 开发(https://launchpad.net/pbr)。pbr 工作运行时会读取和过滤 setup.cfg 中的数据解析后给 setup.py 作为参数。包含如下功能:

  • 从 git 中获取 Version、AUTHORS and ChangeLog 信息
  • Sphinx Autodoc。pbr 会扫描 project,找到所有模块,生成 stub files
  • 读取 requirements.txt,生成 setup 函数需要的 xxx.egg-info/requires.txt

setup.py

import setuptools

try:
    import multiprocessing  # noqa
except ImportError:
    pass

setuptools.setup(
    setup_requires=['pbr>=2.0.0'],
    pbr=True)

setup.cfg

参考:https://opendev.org/openstack/octavia/src/branch/master/setup.cfg

octavia-setup_cfg
[metadata]
name = octavia
summary = OpenStack Octavia Scalable Load Balancer as a Service
description-file =
    README.rst
author = OpenStack
author-email = openstack-discuss@lists.openstack.org
home-page = https://docs.openstack.org/octavia/latest/
python-requires = >=3.6
classifier =
    Development Status :: 5 - Production/Stable
    Environment :: OpenStack
    Intended Audience :: Developers
    Intended Audience :: Information Technology
    Intended Audience :: System Administrators
    License :: OSI Approved :: Apache Software License
    Operating System :: POSIX :: Linux
    Programming Language :: Python
    Programming Language :: Python :: 3
    Programming Language :: Python :: 3.6
    Programming Language :: Python :: 3.7
    Programming Language :: Python :: 3.8

[files]
packages =
    octavia
data_files =
    etc/octavia =
        etc/octavia.conf
    share/octavia =
        LICENSE
        README.rst
    share/octavia/diskimage-create =
        diskimage-create/diskimage-create.sh
        diskimage-create/image-tests.sh
        diskimage-create/README.rst
        diskimage-create/requirements.txt
        diskimage-create/test-requirements.txt
        diskimage-create/tox.ini
        diskimage-create/version.txt

[entry_points]
wsgi_scripts =
    octavia-wsgi = octavia.api.app:setup_app
console_scripts =
    octavia-api = octavia.cmd.api:main
...

[extras]
# Required in case of AmphoraV2 redis jobboard is used
redis =
    redis>=2.10.0
# Required in case of AmphoraV2 zookeeper jobboard is used
zookeeper =
  kazoo>=2.6.0 # Apache-2.0
  zake>=0.1.6 # Apache-2.0

说明:

  • packages: 指定需要包含的包,功能类似于 setuptools.find_packages
  • data_files: 指定目的目录和源文件路径
  • entry_points: 入口,会放到 /usr/local/bin/ 目录下

扩展 setup.cfg 版本信息(python3 setup.py sdist)会在目标文件中自动生成:

...
[egg_info]
tag_build =
tag_date = 0
...

指定版本打包

基于 pbr 的打包,指定 tag 版本会显示为软件包的版本,示例:

  • git 打 tag
git tag v1.0.0
git checkout v1.0.0
  • 打 source 包,打包后可以在 dist/ 目录下找到对应的压缩包
# 默认,下面示例采用该方式
python3 setup.py sdist

# 指定包格式,查看指的到包格式:python2 setup.py bdist --help-formats
python3 setup.py sdist --formats=gztar,zip

# 指定用户
python3 setup.py sdist --owner=root --group=root

# egg 包
python3 setup.py bdist_egg

# rpm 包,更多参考:https://www.xiexianbin.cn/tags/rpmbuild/index.html
yum install rpm-build make gcc -y
python3 setup.py bdist_rpm --help
python3 setup.py bdist_rpm --release=1
  • 查看包的格式
$ cd dist/ && tar -zxvf *.tar.gz
$ tree .
...
├── MANIFEST.in
├── PKG-INFO  # 包版本信息,为 v1.0.0
├── README.rst
├── requirements.txt
├── setup.cfg
├── setup.py
├── test-requirements.txt
└── tox.ini
  • 安装
easy_install xxx.tar.gz

制作 whl

bdist_wheel 命令默认不存在,需要安装如下包后,才能使用:

$ pip3 install wheel check-wheel-contents

制作包

$ python3 setup.py bdist_wheel
$ ls dist/
xxx-py3-none-any.whl

whl 包本质

$ file xxx-py3-none-any.whl
xxx-py3-none-any.whl: Zip archive data, at least v2.0 to extract, compression method=deflate

# 解压
tar -zxvf xxx-py3-none-any.whl

使用 setup.py 安装包

# 正式安装
python3 setup.py install

# 开发模式安装,软链接方式实现
python3 setup.py develop

与pip区别

python setup.py installpip install都是用来安装python包的,实际上,pip提供了更多的特性,更易于使用。体现在以下几个方面:

  • pip 会自动下载依赖,而如果使用 setup.py,则需要手动搜索和下载
  • pip 会自动管理包的信息,使卸载/更新更加方便和容易,使用pip uninstall即可。而使用setup.py,必须手动删除,有时容易出错
  • pip 提供了对 virtualenv 更好的整合

其他

Babel 语言包

  • BabelPython 的一个国际化工具包,提供了对 distutilssetuptools 的支持,包含一些命令。
  1. compile_catalog

类似于msgfmt工具,takes a message catalog from a PO file and compiles it to a binary MO file.

$ ./setup.py compile_catalog --directory foobar/locale --locale pt_BR
running compile_catalog
compiling catalog to foobar/locale/pt_BR/LC_MESSAGES/messages.mo
  1. extract_messages

类似于xgettext,it can extract localizable messages from a variety of difference source files, and generate a PO (portable object) template file from the collected messages.

$ ./setup.py extract_messages --output-file foobar/locale/messages.pot
running extract_messages
extracting messages from foobar/__init__.py
extracting messages from foobar/core.py
...
writing PO template file to foobar/locale/messages.pot
  1. update_catalog

类似于msgmerge,it updates an existing translations catalog based on a PO template file (POT).

参考

  1. https://pypi.org/project/setuptools/
  2. https://setuptools.pypa.io/en/latest/setuptools.html
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数