美文网首页Python学习分享
Python程序包的构建和发布过程

Python程序包的构建和发布过程

作者: 烟雨丿丶蓝 | 来源:发表于2019-06-09 13:59 被阅读15次

    当我们开发了一个开源项目时,就希望把这个项目打包然后发布到 pypi.org 上,别人就可以通过 pip install 的命令进行安装。本文的教程来自于 Python 官方文档如有不正确的地方欢迎评论拍砖。

    在这推荐下小编创建的Python学习交流群835017344,可以获取Python入门基础教程,送给每一位小伙伴,这里是小白聚集地,每天还会直播和大家交流分享经验哦,欢迎初学和进阶中的小伙伴。


    0x00 创建项目

    本文使用到的项目目录为

    <pre class="prettyprint hljs vim" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">➜ packaging-tutorial
    .
    └── bestpkg
    └── init.py
    复制代码</pre>

    接下来的所有操作都是在 packing_tutorial 这个目录下进行的。首先把 bestpkg 这个目录下的 __init__.py 添加以下内容

    <pre class="hljs tcl" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 0.75em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">info='packaging demo'
    复制代码</pre>

    这个信息主要用于打包成功后安装测试用的。

    0x01 项目结构

    一个待发布的项目还需要有以下这些文件: setup.pyLICENSEREADME.md

    <pre class="prettyprint hljs css" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">➜ packaging-tutorial
    .
    ├── LICENSE
    ├── README.md
    ├── bestpkg
    │ └── init.py
    └── setup.py
    复制代码</pre>

    0x02 setup.py

    setup.py 文件是给 setuptools 工具的使用脚本,告诉 setuptools 如何构建我们的项目。打开编辑器,编辑 setup.py 文件,输入以下内容

    <pre class="prettyprint hljs python" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">import setuptools

    读取项目的readme介绍

    with open("README.md", "r") as fh:
    long_description = fh.read()

    setuptools.setup(
    name="bestpkg",# 项目名称,保证它的唯一性,不要跟已存在的包名冲突即可
    version="0.0.1",
    author="hylinux1024", # 项目作者
    author_email="hylinux1024@gmail.com",
    description="一个牛逼的程序", # 项目的一句话描述
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/hylinux1024/niubiproject",# 项目地址
    packages=setuptools.find_packages(),
    classifiers=[
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
    ],
    )
    复制代码</pre>

    • name
      项目名称,保证它的唯一性,不要跟已存在的包名冲突即可,否则会发布失败
    • version
      版本号
    • author
      作者
    • author_email
      作者邮箱
    • description
      一句话描述项目
    • long_description
      项目详细说明,一般直接读取README.md的内容
    • url
      项目的链接地址
    • packages
      列出当前项目的包,一般直接使用 find_packages() 即可
    • classifiers
      这里指定 Python 的兼容版本是 Python3 ,也指定了项目使用的开源协议。

    0x03 README.md

    给项目添加详细的 README

    <pre class="prettyprint hljs markdown" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># Example Package

    This is a simple example package. You can use
    Github-flavored Markdown
    to write your content.
    复制代码</pre>

    0x04 LICENSE

    要发布包到 pypi 上,选择一个合适的开源协议是非常重要的。如果不知道怎么选可以到choosealicense.com/这里看看。

    0x05 项目打包

    项目需要打包后才能发布,要打包项目需先安装最新版本的 setuptoolswheel

    <pre class="prettyprint hljs sql" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">➜ python3 -m pip install --user --upgrade setuptools wheel
    复制代码</pre>

    然后使用以下命令进行打包

    <pre class="hljs vim" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 0.75em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">➜ python3 setup.py sdist bdist_wheel
    复制代码</pre>

    当看到以下信息,说明已经打包成功

    <pre class="prettyprint hljs gradle" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">...
    ...
    ...
    adding license file "LICENSE" (matched pattern "LICEN[CS]E*")
    creating build/bdist.macosx-10.14-x86_64/wheel/bestpkg-0.0.1.dist-info/WHEEL
    creating 'dist/bestpkg-0.0.1-py3-none-any.whl' and adding 'build/bdist.macosx-10.14-x86_64/wheel' to it
    adding 'bestpkg/init.py'
    adding 'bestpkg-0.0.1.dist-info/LICENSE'
    adding 'bestpkg-0.0.1.dist-info/METADATA'
    adding 'bestpkg-0.0.1.dist-info/WHEEL'
    adding 'bestpkg-0.0.1.dist-info/top_level.txt'
    adding 'bestpkg-0.0.1.dist-info/RECORD'
    removing build/bdist.macosx-10.14-x86_64/wheel
    复制代码</pre>

    在项目目录下会生成一个 distbuild 文件夹

    <pre class="prettyprint hljs css" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">➜ packaging-tutorial tree
    .
    ├── LICENSE
    ├── README.md
    ├── bestpkg
    │ └── init.py
    ├── bestpkg.egg-info
    │ ├── PKG-INFO
    │ ├── SOURCES.txt
    │ ├── dependency_links.txt
    │ └── top_level.txt
    ├── build
    │ ├── bdist.macosx-10.14-x86_64
    │ ├── bdist.macosx-10.9-x86_64
    │ └── lib
    │ └── bestpkg
    │ └── init.py
    ├── dist
    │ ├── bestpkg-0.0.1-py3-none-any.whl
    │ └── bestpkg-0.0.1.tar.gz
    └── setup.py

    8 directories, 11 files
    复制代码</pre>

    dist 文件中有两个文件

    <pre class="prettyprint hljs css" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">dist
    ├── bestpkg-0.0.1-py3-none-any.whl
    └── bestpkg-0.0.1.tar.gz
    复制代码</pre>

    tar.gz 文件是源码文件压缩包,而 .whl 就是打包后的文件。最新的 pip 命令会安装这个 .whl 文件。

    0x06 上传

    现在就可以上传到 Python 索引库了。我们使用 Test PyPI ,这个是测试用的 Pypi ,本例子也是使用 Test Pypi

    首先要到 test.pypi.org/account/reg… 注册账号。本例中我注册的账号为: hylinux1024

    然后使用 twine 工具来上传我们的包。使用以下命令进行安装:

    <pre class="hljs sql" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 0.75em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">➜ python3 -m pip install --user --upgrade twine
    复制代码</pre>

    使用以下命令上传 dist 目录下的文件

    <pre class="prettyprint hljs ruby" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">➜ python3 -m twine upload --repository-url https://test.pypi.org/legacy/ dist/*
    复制代码</pre>

    这个命令会提示输入刚在 test.pypi.org 上注册账号密码,并出现类似以下信息后说明已经上传成功。

    <pre class="prettyprint hljs groovy" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">Enter your username: hylinux1024
    Enter your password:
    Uploading distributions to https://test.pypi.org/legacy/
    Uploading bestpkg-0.0.1-py3-none-any.whl
    100%|██████████████████████████████████████| 4.57k/4.57k [00:00<00:00, 8.01kB/s]
    Uploading bestpkg-0.0.1.tar.gz
    100%|██████████████████████████████████████| 4.18k/4.18k [00:01<00:00, 3.23kB/s]
    复制代码</pre>

    然后打开 test.pypi.org/project/bes… 这个地址就可以看到我们发布的包。

    0x07 安装

    发布成功之后就可以使用 pip 来安装来。我们在虚拟环境中安装,关于虚拟环境可以看我前一篇文章。

    这里就使用 pipenv ,这里我直接进入到我昨天创建的那个项目中,也为了更好演示安装结果。

    <pre class="prettyprint hljs vim" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">➜ pip install --index-url https://test.pypi.org/simple/ --no-deps bestpkg
    复制代码</pre>

    在这里我使用 --index-url 参数是为了指定从 test.pypi.org 中安装,而不是正式包索引库中查找要安装的包。还有使用了 --no-deps 参数是因为本例中没有使用到其它的依赖库。

    在终端会看到以下类似信息,说明安装成功

    <pre class="prettyprint hljs groovy" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">Looking in indexes: https://test.pypi.org/simple/
    Collecting bestpkg
    Downloading https://test-files.pythonhosted.org/packages/5a/fc/c109b3872b6c06e7368c30b6e52501113846f90ca716a434766151093173/bestpkg-0.0.1-py3-none-any.whl
    Installing collected packages: bestpkg
    Successfully installed bestpkg-0.0.1
    复制代码</pre>

    进入交互界面

    <pre class="prettyprint hljs ruby" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">(pipenvdemo) ➜ pipenvdemo python

    import bestpkg
    bestpkg.info
    'packaging demo'
    复制代码</pre>

    info 变量就是在 __init__.py 文件中定义的变量。自此我们的包发布、安装使用流程就走完了。

    要在正式的 Python 索引库中发布,只需要到pypi.org/注册账号,并上传就可以了。

    0x08 总结一下

    通过一个简单的例子展示 Python 通过 setuptools 工具进行打包,然后上传到 test.pypi.org的流程。如果要上传到正式的 pypi.org 上,只需要注册一个正式的账号。一旦发布成功就可以使用 pip install [your-package] 的命令进行安装。

    相关文章

      网友评论

        本文标题:Python程序包的构建和发布过程

        本文链接:https://www.haomeiwen.com/subject/lkxnxctx.html