如何在 PyPI 发布自己的 Python 包

前置条件

  • 拥有 PyPI 账号,若没有,可点击注册

  • 开发机「自己的电脑」安装 Twine

pip install twine

正式开始

代码目录结构

my_pkg 是一个正常编写的 Python 包

.
├── my_pkg
│   ├── __init__.py
│   └── my_function.py
├── setup.py
└── README.md

有些包在安装之后会自动生成一个可执行命令,如 pip install twine 之后,就可以直接在命令行使用 twine 命令,想要达到这种效果可以在 Python 包中增加一个 py

.
├── my_pkg
│   ├── __init__.py
│   ├── my_cmd.py            # 若想在安装的时候自动生成一个可执行命令,则可增加一个方法
│   └── my_function.py
├── setup.py
└── README.md

编写 setup.py

setup.py 是关键,附上我自用的样本

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from setuptools import find_packages, setup
import os

# 提供一些有用的信息
URL = 'https://github.com/seoktaehyeon/api-test-framework'    # 通常会附上 GitHub 地址
NAME = 'ApiTestFramework'                                     # Python 包的名称,即在 pip install 时后面跟的包名
VERSION = '0.1.1'                                             # 包的版本,每次上传到 PyPI 都需要改变这个版本号,否则只会往存储空间增加新内容,无法达到预期
DESCRIPTION = 'Api test framework in Linux'                   # 关于该包的剪短描述
if os.path.exists('README.md'):                               # 如果需要,可以加入一段较长的描述,比如读取 README.md,该段长描述会直接显示在 PyPI 的页面上
    with open('README.md', encoding='utf-8') as f:
        LONG_DESCRIPTION = f.read()
else:
    LONG_DESCRIPTION = DESCRIPTION
AUTHOR = 'Will'                                               # 留下大名
AUTHOR_EMAIL = 'v.stone@163.com'                              # 留下邮箱
LICENSE = 'MIT'                                               # 定义合适自己的许可证,实在不知道,那就 MIT 吧
PLATFORMS = [                                                 # 支持的平台,如果所有平台都支持,可以填 all
    'linux',
]
REQUIRES = [                                                  # 很多时候,我自己写的包都要依赖第三方,所以可以把依赖包定义在这里,这样的 pip install 自己包的时候,顺便把这些依赖包都装上了
    'PyYAML>=5.2',
    'requests>=2.22.0',
    'pytest>=5.3.2',
    'pytest-html>=2.0.1',
]
CONSOLE_SCRIPT = 'my-cmd=my_pkg.my_cmd:main'                  # 如果想在 pip install 之后自动生成一个可执行命令,就靠它了: 
                                                              # <command>=<package_name>.<python_file_name>:<python_function>
                                                              # 值得注意的是:
                                                              # python_file_name 是不能用"-"的,需要用"_",但 command 可以用"-"
                                                              # my_cmd.py 也很简单,正常写即可,方法名也不一定是 main

# 需要的信息就在 setup() 中加上,不需要的可以不加
setup(
    name=NAME,
    version=VERSION,
    description=(
        DESCRIPTION
    ),
    long_description=LONG_DESCRIPTION,
    long_description_content_type='text/markdown',
    author=AUTHOR,
    author_email=AUTHOR_EMAIL,
    maintainer=AUTHOR,
    maintainer_email=AUTHOR_EMAIL,
    license=LICENSE,
    packages=find_packages(),
    platforms=PLATFORMS,
    url=URL,
    install_requires=REQUIRES,
    entry_points={
        'console_scripts': [CONSOLE_SCRIPT],
    }
)

打包

利用 setuptools 打包

  • sdist —— Source Distribution
  • bdist_wheel —— Wheel Binary Distribution
python setup.py sdist bdist_wheel

上传

利用 twine 上传打包的好的文件,使用 twine 时候,会提示要求输入 PyPI 的帐密

twine upload dist/*
#Uploading distributions to https://upload.pypi.org/legacy/
#Enter your username: 
#Enter your password: 

成果展示

我的第一个 PyPI 包,安装完 ApiTestFramework 之后,会生成一个 atf-exec 命令

/ # pip install ApiTestFramework
Collecting ApiTestFramework
  Downloading https://files.pythonhosted.org/packages/96/e5/110573cf2652e852a9cd513623ddbf1c710ddd55442831d824b0f27820ae/ApiTestFramework-0.1.1-py3-none-any.whl
Collecting PyYAML>=5.2 (from ApiTestFramework)
  Downloading https://files.pythonhosted.org/packages/8d/c9/e5be955a117a1ac548cdd31e37e8fd7b02ce987f9655f5c7563c656d5dcb/PyYAML-5.2.tar.gz (265kB)
     |████████████████████████████████| 266kB 8.0kB/s
Collecting requests>=2.22.0 (from ApiTestFramework)
  Downloading https://files.pythonhosted.org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/requests-2.22.0-py2.py3-none-any.whl (57kB)
     |████████████████████████████████| 61kB 18kB/s
Collecting pytest-html>=2.0.1 (from ApiTestFramework)
  Downloading https://files.pythonhosted.org/packages/f9/8d/c79a92919ada2986f6dab1bc7cf7ba86160c513cb8aa254ad0e2f940f96a/pytest_html-2.0.1-py2.py3-none-any.whl
Collecting pytest>=5.3.2 (from ApiTestFramework)
......
Installing collected packages: PyYAML, idna, certifi, chardet, urllib3, requests, six, pyparsing, packaging, py, wcwidth, more-itertools, zipp, importlib-metadata, attrs, pluggy, pytest, pytest-metadata, pytest-html, ApiTestFramework
Successfully installed ApiTestFramework-0.1.2 PyYAML-5.2 attrs-19.3.0 certifi-2019.11.28 chardet-3.0.4 idna-2.8 importlib-metadata-1.3.0 more-itertools-8.0.2 packaging-19.2 pluggy-0.13.1 py-1.8.0 pyparsing-2.4.5 pytest-5.3.2 pytest-html-2.0.1 pytest-metadata-1.8.0 requests-2.22.0 six-1.13.0 urllib3-1.25.7 wcwidth-0.1.7 zipp-0.6.0
/ # atf-exec
Usage: atf-exec option
option:
    init    Init framework
    prepare Generate test case in test_case dir and data template in data_template dir
    run     Run test case
    clean   Clean up workspace
/ #
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351