Python——自定义pip包的安装和打包


整体说明

  • 打包本地项目为的 pip 包时,可以使用 pip install . 命令
  • 执行 pip install . 命令时,Python 包管理工具 pip 会根据当前目录中的 setup.py 文件来安装包
    • 这个过程涉及多个步骤,包括解析包的元数据、处理依赖关系、构建和安装包等
    • 安装的内容包括包的所有模块、数据文件、编译文件以及命令行工具
    • 默认情况下,只安装核心依赖,可选依赖需要用户显式指定

构建一个包的步骤

第一步:解析和构建

  • 解析 setup.py (setup.py 的详细示例见附录):
    • pip 首先会查找并解析当前目录中的 setup.py 文件
    • 读取包的元数据(如包名、版本、作者信息等)和安装选项(如 install_requiresextras_require 等)
  • 构建包:
    • pip 会使用 setuptoolsdistutils 来构建包
    • 包的构建包括编译C扩展(如果存在)、处理包内的数据文件等
    • 生成一个源代码分发包(Source Distribution,简称 sdist)或一个二进制分发包(Binary Distribution,简称 wheel

第二步:处理依赖

  • 安装核心依赖
    • pip 会根据 setup.py 中的 install_requires 列表安装包的核心依赖
    • 这些依赖是包运行所必须的
  • 可选依赖
    • 如果用户在命令中指定了可选依赖组(如 pip install .[dev]),pip 会安装对应的 extras_require 可选依赖
    • 否则,默认情况下不会安装 extras_require 中的可选依赖

第三步:安装包**

  • 导入包和模块
    • pip 会将构建好的包安装到Python环境的 site-packages 目录中
    • 包中的所有模块和子包都会被导入
  • 包数据文件
    • 如果 setup.py 中设置了 include_package_data=True 或指定了 package_data,这些数据文件也会被安装
  • 命令行工具
    • 如果 setup.py 中定义了 entry_points,对应的命令行工具会被安装并注册

第四步:打包内容

  • 包和模块
    • 所有通过 packagesfind_packages() 指定的包和模块
  • 数据文件
    • 通过 package_datainclude_package_data 指定的额外数据文件
  • 编译文件
    • 如果包中包含 C/C++ 扩展模块,这些模块会被编译并打包

附录:setup.py 文件的示例

  • setup.py 文件是 Python 项目中用于定义包的元数据、依赖关系及其他安装相关信息的脚本
  • setup.py 文件主要通过 setuptoolsdistutils 库来实现包的配置和分发

setup.py 文件示例

  • setup.py 文件基本结构示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    from setuptools import setup, find_packages

    setup(
    name="package_name", # 包名
    version="0.1.0", # 版本号
    author="Author Name", # 作者
    author_email="author@example.com", # 作者邮箱
    description="A short description", # 简短描述
    long_description=open("README.md").read(), # 长描述(通常从README文件导入)
    long_description_content_type="text/markdown", # 长描述类型(如Markdown)
    url="https://github.com/username/repo", # 项目URL
    packages=find_packages(), # 自动发现并包含所有包
    classifiers=[ # 分类标签(如开发状态、受众、许可证)
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
    ],
    python_requires='>=3.6', # Python版本要求
    install_requires=[ # 安装依赖
    "requests>=2.25.0",
    "numpy",
    ],
    extras_require={ # 可选依赖(如开发、测试)
    "dev": ["pytest", "sphinx"],
    },
    entry_points={ # 命令行工具入口
    "console_scripts": [
    "mycommand=mypackage.module:function",
    ],
    },
    include_package_data=True, # 包含包内数据文件
    package_data={ # 指定包数据文件
    "mypackage": ["data/*.dat"],
    },
    zip_safe=False, # 是否允许打包为zip文件
    )

主要内容和功能说明

  • 元数据:
    • name : 包的名称
    • version : 包的版本号,通常遵循语义版本规范(如 MAJOR.MINOR.PATCH
    • authorauthor_email : 作者的姓名和联系邮箱
    • descriptionlong_description : 包的简短和详细描述
    • url : 项目的主页或代码仓库地址
  • 包和模块:
    • packages : 指定需要包含的包列表,通常使用 find_packages() 自动发现
    • package_data : 指定需要包含的非代码文件(如数据文件、模板等)
  • 依赖管理:
    • install_requires : 安装包时需要满足的依赖列表
    • extras_require : 可选依赖,按功能分组(如开发依赖、测试依赖)
  • Python 版本:
    • python_requires : 指定包支持的Python版本范围
  • 分类标签:
    • classifiers : 用于描述包的特性和分类,帮助用户和工具识别包的适用性
  • 命令行工具:
    • entry_points : 定义包提供的命令行工具及其入口函数
  • 数据文件:
    • include_package_data : 是否包含包内的额外数据文件
  • 打包选项:
    • zip_safe : 指定包是否可以安全地打包为zip文件

附录:setup.py 中的 extras_require 使用

  • setup.py 中定义的 extras_require 提供了一种机制,可以按需安装额外的依赖项

  • extras_require 允许定义一些可选的依赖组,比如开发依赖、测试依赖等

  • 举例来说,前面附录小节的示例中 extras_require 中定义了一个名为 “dev” 的组和对应的依赖

  • 默认情况下 ,安装包时不会自动安装 extras_require 中定义的可选依赖项

    • 直接使用 pip install .pip install package_name 安装包即可
    • 在这种情况下,只有 install_requires 中定义的核心依赖会被安装
  • 安装可选依赖,以 安装 “dev” 组的可选依赖 为例:

    • 使用 pip 安装时,可以通过在包名后加上 [dev] 来指定安装这些可选依赖

      1
      pip install .[dev]
    • 如果包已经发布到PyPI或其他包管理平台,可以使用以下命令:

      1
      pip install package_name[dev]