一、开发者视角:如何为你的项目创建和维护 setup.py

作为项目的开发者,你的目标不仅仅是让代码能够运行,更是要让它变得可分发、可安装、可复用setup.py 就是实现这一目标的核心工具。

为什么要创建 setup.py
  1. 标准化安装:让任何人都能用一句 pip install -e . 来安装你的项目,而不是去手动复制文件、猜测依赖。
  2. 依赖管理:在文件中明确声明你的项目依赖哪些第三方库(如 requests, numpy)。pip 在安装你的项目时会自动处理这些依赖。
  3. 创建命令行工具:可以将你代码中的某个函数直接变成一个可以在终端(Terminal/Shell)里运行的命令。
  4. 发布到 PyPI:如果你想让全世界的开发者都能通过 pip install your-project-name 安装你的项目,setup.py 是必不可少的一步。
创建 setup.py 的步骤

setup.py 不是自动生成的,而是需要你根据项目情况手动编写。假设你的项目结构如下:

my_project/
├── my_awesome_tool/
│   ├── __init__.py
│   ├── main.py
│   ├── __version__.py
│   └── utils.py
├── tests/
│   └── test_main.py
├── README.md
└── setup.py   <-- 我们要创建的文件

第1步:编写 setup.py 骨架

创建一个 setup.py 文件,并从 setuptools 导入 setupfind_packages

from setuptools import setup, find_packages

第2步:管理版本号(最佳实践)

为了方便维护,在你的主包 my_awesome_tool 里创建一个 __version__.py 文件。

# my_awesome_tool/__version__.py 的内容
__version__ = "0.1.0"

然后在 setup.py 中动态读取它:

# setup.py
...
exec(open('my_awesome_tool/__version__.py').read())

第3步:填写核心配置

现在,调用 setup() 函数并填入所有信息。
一个典型的 setup.py 文件内容如下:

# setup.py

from setuptools import setup, find_packages

# 动态加载版本号
exec(open('my_awesome_tool/__version__.py').read())

setup(
    # 1. 基本信息
    name="my-awesome-tool",  # 包名,pip install 时使用
    version=__version__,     # 版本号
    author="你的名字",
    author_email="你的邮箱@example.com",
    description="一个能做很棒事情的工具",
    url="https://github.com/your_username/my_project", # 项目链接

    # 2. 查找要打包的代码
    packages=find_packages(exclude=["tests"]), # 自动查找所有包,并排除 tests 目录

    # 3. 声明项目依赖 (非常重要!)
    install_requires=[
        'requests>=2.20',
        'numpy',
        'click', # 假设我们用它来创建命令行工具
    ],

    # 4. 创建命令行工具 (可选但常用)
    entry_points={
        'console_scripts': [
            'awesome_tool=my_awesome_tool.main:cli',
        ],
    },

    # 5. 其他元数据
    license="MIT",
    python_requires='>=3.9', # 声明需要的 Python 版本
)

关键点解释:

  • install_requires: 这是最重要的字段之一。它是一个列表,列出了你的项目正常运行所必需的第三方库。当用户安装你的包时,pip 会自动安装列表中的所有依赖。
  • entry_points: 这是创建命令行工具的“魔法”。'awesome_tool=my_awesome_tool.main:cli' 的意思是:创建一个名为 awesome_tool 的命令,当它被执行时,去运行 my_awesome_tool 包里 main.py 文件中的 cli 函数。

完成这个文件后,你的项目就变成了一个标准的、可安装的 Python 包了。


二、用户视角:如何使用 setup.py 来安装项目

作为用户,你从 GitHub 或其他地方下载了一个包含 setup.py 的项目。你的目标是快速、正确地在你的电脑上把它运行起来。

准备工作:创建虚拟环境

这是一个绝对推荐的最佳实践,可以避免污染你的全局 Python 环境。

# 进入项目根目录 (包含 setup.py 的地方)
cd my_project
# 创建一个名为 venv 的虚拟环境
python -m venv venv
# 激活虚拟环境
# macOS/Linux:
source venv/bin/activate
# Windows:
venv\Scripts\activate
------------------------
conda create -n myproject python=3.x
conda activate myproject
-------------------------

现在你的终端提示符前面应该有一个 (venv),表示你正处于这个隔离的环境中。(或者conda的虚拟环境(myproject))

安装项目

你有两种主要的安装方式,取决于你的目的。

方式一:可编辑模式 (Editable Mode) - 适用于开发者和贡献者

如果你打算修改这个项目的代码,或者你是项目的原作者换了一台新电脑,那么应该使用这种模式。

pip install -e .
  • -e 代表 editable (可编辑)。
  • . 代表当前目录。

工作原理:这种模式不会把代码文件复制到你的 Python 环境的 site-packages 目录里。相反,它会创建一个“链接”,直接指向你当前的项目源代码。

最大好处:你对源代码的任何修改都会立刻生效,无需重新安装。这对于开发和调试来说是无价的。

方式二:标准模式 (Standard Mode) - 适用于普通用户

如果你只是想把这个项目当作一个第三方库来使用,不打算修改它的代码,那么就用标准模式。

pip install .

工作原理:这会像从 PyPI 安装其他库一样,将项目文件“构建”并复制到你的虚拟环境的 site-packages 目录中。这是一个更稳定、更隔离的安装方式。

安装之后

无论你用哪种方式安装,完成后pip都会自动读取 setup.py文件,并为你安装好所有在install_requires中声明的依赖包:

  1. setup.pyinstall_requires 列出的所有依赖(如requests, numpy)都已被自动安装。
  2. 如果你安装的项目定义了 entry_points,那么相应的命令现在就可以在终端里直接使用了(例如,可以直接运行 awesome_tool 命令)。
  3. 你可以在任何地方启动 Python 解释器,然后 import my_awesome_tool 来使用这个库。

随着社区的发展,使用一个可执行的 Python 文件 (setup.py) 来定义项目配置的方式暴露出一些弊端。因此,Python 社区推出了一个更现代、更标准的配置文件:pyproject.toml

这是一个静态的 TOML 格式文件,旨在成为项目配置的唯一入口,统一管理项目元数据、构建系统和工具配置。

一个等效的pyproject.toml可能如下所示:

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "my-awesome-tool"
version = "0.1.0" # 在这里可以直接定义,或从文件中读取
authors = [ {name = "你的名字"} ]
description = "一个功能强大的工具"
requires-python = ">=3.9"
dependencies = [
    "requests>=2.20",
    "numpy",
    "click",
]

[project.scripts]
awesome_tool = "my_awesome_tool.main:cli"

对于新项目,我们强烈推荐直接使用pyproject.toml,因为它代表了 Python 打包生态的未来方向。不过,理解 setup.py 依然非常重要,因为它在数百万个现有项目中仍被广泛使用。

更多推荐