杰瑞科技汇

python distutils使用

distutils 是 Python 的一个标准库模块,用于构建和分发 Python 模块,它的主要目标是让开发者能够轻松地将自己的 Python 代码打包成标准的分发包(如 .tar.gz.zip 文件),以便其他用户可以轻松地安装。

python distutils使用-图1
(图片来源网络,侵删)

distutils 的核心概念

在使用 distutils 之前,需要理解几个核心概念:

  • Setup Script: 一个名为 setup.py 的 Python 脚本,这是整个打包过程的入口和配置文件,它告诉 distutils 关于你的项目(如名称、版本、作者、依赖等)以及如何构建它。
  • Distribution: 指的是你打包好的最终产物,例如一个源码分发包(.tar.gz)或一个二进制分发包(.zip.whl)。
  • Module/Package: 你想要分发的 Python 代码本身,一个模块是一个 .py 文件,一个包是一个包含 __init__.py 文件的目录。
  • Metadata: 关于你项目的描述信息,如名称、版本、作者、邮箱、许可证等,这些信息会写入生成的分发包中。

创建一个简单的 setup.py 文件

这是使用 distutils 的第一步,我们从一个最简单的例子开始。

假设你有一个简单的项目结构:

my_project/
├── my_module/
│   ├── __init__.py
│   └── hello.py
└── setup.py

my_module/hello.py 的内容如下:

python distutils使用-图2
(图片来源网络,侵删)
# my_module/hello.py
def say_hello(name):
    """A simple function to say hello."""
    print(f"Hello, {name}!")

my_module/__init__.py 的内容如下(使其成为一个包):

# my_module/__init__.py
from .hello import say_hello

我们来创建 setup.py 文件:

# setup.py
from distutils.core import setup
setup(
    name="MySimpleModule",
    version="0.1.0",
    description="A very simple Python module example.",
    author="Your Name",
    author_email="your.email@example.com",
    packages=["my_module"],
)

setup() 函数参数详解:

  • name: 分发包的名称。
  • version: 分发包的版本号。
  • description: 项目的简短描述。
  • author: 作者姓名。
  • author_email: 作者邮箱。
  • packages: 一个列表,包含了所有需要分发的包。distutils 会自动在项目目录下查找这些包,这里我们指定了 my_module

常用的 setup() 参数

setup() 函数有很多参数,下面是一些最常用的:

python distutils使用-图3
(图片来源网络,侵删)

1. 项目信息

  • long_description: 项目的详细描述,通常从 README.mdREADME.rst 文件中读取,在 PyPI 上显示时非常有用。
  • url: 项目的主页或代码仓库 URL。
  • license: 项目的许可证,如 "MIT", "Apache 2.0", "GPLv3"。

示例:

import os
from distutils.core import setup
# 读取 README 文件内容作为 long_description
this_directory = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f:
    long_description = f.read()
setup(
    name="MySimpleModule",
    version="0.1.0",
    description="A very simple Python module example.",
    long_description=long_description,
    long_description_content_type="text/markdown", # 如果是 Markdown 格式
    url="https://github.com/yourusername/my_project",
    author="Your Name",
    author_email="your.email@example.com",
    license="MIT",
    packages=["my_module"],
)

2. 依赖管理

  • install_requires: 一个列表,指定了你的项目在运行时依赖的其他库,当用户安装你的包时,pip 会自动安装这些依赖。

示例:

setup(
    # ... 其他参数 ...
    install_requires=[
        "requests >= 2.20.0",
        "numpy >= 1.15.0",
        "Pillow", # 没有版本号表示安装最新版本
    ],
)

3. 包含非 Python 文件

默认情况下,distutils 只会包含 Python 文件,如果你需要包含其他文件(如配置文件、数据文件、C 源码等),可以使用以下参数:

  • package_data: 指定需要包含在特定包内的数据文件。
  • data_files: 指定需要安装到特定位置的数据文件(不一定是包内)。

package_data 示例:

假设你的项目结构如下:

my_project/
├── my_module/
│   ├── __init__.py
│   └── hello.py
│   └── data/
│       └── config.json
└── setup.py

你想把 config.jsonmy_module/data/ 目录下的所有 .txt 文件一起打包:

from distutils.core import setup
setup(
    # ... 其他参数 ...
    packages=["my_module"],
    package_data={
        'my_module': ['data/config.json', 'data/*.txt'],
    },
)

运行 setup.py 命令

在终端中,进入 my_project 目录,就可以对 setup.py 执行各种命令了。

1. 构建分发包

这是最常用的命令,它会创建一个 dist/ 目录,里面包含源码分发包(.tar.gz)。

python setup.py sdist

执行后,你会看到:

running sdist
running check
...
writing list of files to ...
creating dist
...
creating dist/MySimpleModule-0.1.0.zip
...

dist/ 目录下会生成 MySimpleModule-0.1.0.zipMySimpleModule-0.1.0.tar.gz

2. 安装包

你可以将你刚创建的分发包安装到当前的 Python 环境中。

# 从分发包安装
pip install dist/MySimpleModule-0.1.0.tar.gz
# 或者直接使用 setup.py 安装(不推荐用于生产,但方便测试)
python setup.py install

安装后,你就可以在 Python 代码中导入并使用你的模块了:

>>> import my_module
>>> my_module.say_hello("World")
Hello, World!

3. 其他常用命令

  • python setup.py --help: 显示所有可用的命令及其帮助信息。
  • python setup.py --help-commands: 显示所有可用的构建命令。
  • python setup.py build: 只构建,不创建分发包,通常在 sdistbdist 命令内部调用。
  • python setup.py clean: 清理构建过程中产生的临时文件(如 build/ 目录)。

distutils vs. setuptools vs. distutils2 / packaging

这是一个非常重要的历史和概念辨析。

工具/库 状态 关系和用途
distutils 标准库,已过时 Python 自带的打包工具,功能有限,不支持依赖管理、现代的构建后端(如 setuptoolsbdist_wheel)等。新项目不应再单独使用它。
setuptools 事实标准,强烈推荐 distutils 的超集,它扩展了 distutils 的功能,并修复了其许多问题。现代 Python 项目开发的首选,它引入了 find_packages()install_requiresentry_pointswheel 等关键功能。
distutils2 已废弃 最初是 distutils 的继任者,旨在成为标准库的一部分,但最终项目停滞,其功能被 setuptoolspackaging 等库吸收。
packaging 现代标准库,用于元数据 一个专注于处理 Python 包元数据和规范的库(如版本号、环境标记),它本身不用于构建,而是被 setuptoolspipwheel 等工具广泛使用。

对于任何新的 Python 项目,请直接使用 setuptools,而不是 distutils

setuptoolssetup.pydistutils 的用法基本兼容,只是提供了更多强大的功能,你可以用 setuptoolsfind_packages() 自动发现所有包:

# 使用 setuptools 的写法
from setuptools import setup, find_packages
setup(
    name="MyProject",
    version="0.1.0",
    packages=find_packages(), # 自动查找所有包
    install_requires=[
        "requests",
    ],
)

现代替代方案:pyproject.tomlbuild 工具

尽管 setup.py + setuptools 仍然是主流,但 Python 社区正在向一种更现代、更标准化的构建方式过渡。

  • pyproject.toml: 一个新的配置文件标准,用于项目的构建系统、依赖和元数据,它取代了 setup.py 中大量的配置信息。
  • build 工具: 一个新的、标准的 Python 包构建工具,它不关心你的项目是如何构建的(是 setuptoolsflit 还是 poetry),它只负责读取 pyproject.toml 并构建出符合标准的分发包(.whl.tar.gz)。

为什么这是一个进步?

  1. 标准化: 所有项目都使用相同的配置文件格式 (pyproject.toml),消除了对 setup.py 脚本安全性的担忧(setup.py 是以 Python 代码执行的,可能包含恶意代码)。
  2. 分离: 构建配置 (pyproject.toml) 和构建逻辑(setuptools 的内部机制)分离开,更清晰。
  3. 简化: 对于简单的项目,使用像 flitpoetry 这样的工具,你几乎不需要写任何 setup.py 代码。

如何使用 build 工具?

  1. 安装 build:

    pip install build
  2. 创建 pyproject.toml: 在你的项目根目录下创建一个 pyproject.toml 文件。setuptools 也支持使用它来配置项目。

    # pyproject.toml
    [build-system]
    requires = ["setuptools>=45", "wheel"]
    build-backend = "setuptools.build_meta"
    [project]
    name = "MySimpleModule"
    version = "0.1.0"
    description = "A very simple Python module example."
    authors = [
        {name = "Your Name", email = "your.email@example.com"},
    ]
    license = {text = "MIT"}
    readme = "README.md"
    requires-python = ">=3.7"
    dependencies = [
        "requests >= 2.20.0",
    ]
    [tool.setuptools]
    packages = ["my_module"]
  3. 构建: 你不再需要运行 python setup.py sdist,而是运行:

    python -m build

    这会读取 pyproject.toml,并使用 setuptools 在后台完成构建,最终在 dist/ 目录生成分发包。


总结与建议

场景 推荐工具 理由
学习 Python 打包基础 distutils 理解核心概念(setup.py, sdist 等)的起点。
维护旧项目 distutils / setuptools 如果项目已经使用 distutils,可以继续维护,但建议迁移到 setuptools 以获得更多功能。
新项目开发 setuptools + pyproject.toml 目前最主流、最平衡的选择,功能强大,社区支持好,并且正在向 pyproject.toml 标准过渡。
追求极简配置的新项目 flitpoetry 如果你的项目非常简单,不想写复杂的配置,flit 是一个极好的选择,它只需要很少的配置。poetry 则是一个集成了依赖管理和打包的“一站式”工具。
遵循最新标准 build 工具 + pyproject.toml 这是未来的方向,无论你使用 setuptools, flit 还是 poetry,最终都推荐使用 python -m build 来构建你的包。

对于绝大多数开发者来说,setuptoolspyproject.toml 开始学习是当前的最佳实践,但理解 distutils 的工作原理对于阅读旧项目代码和打包历史仍然非常有价值。

分享:
扫描分享到社交APP
上一篇
下一篇