从零开始制作年轻人的第一款pip包

本文由 简悦 SimpRead 转码, 原文地址 sspai.com

近期在雾凇拼音项目的帮助下入坑了 rime,现在已经是我日常必备的软件。然而 rime 使用过程中有一个很大的不便是词库问题,虽然已经有深蓝词库转换可以支持词库间的转换,但依然存在一些特定情况,需要特殊处理。

比如我搜索不到医学相关的专业英语词库,所以只能爬取一些术语进行处理,自己制作一个词库,为了解决这类问题,我用自己为数不多的 python 能力写了一个 jupyter,但是每次使用都要打开 VSCode - 打开文件 - 选择 python 环境 - 运行 jupyter

非常心累:pensive:

那我能不能做成命令行呢?

我非常喜欢的 bilix,就是一款很方便的命令行工具,只要打开终端,输入几个字母,剩下的依靠终端自动补全,最后黏贴一下链接,回车即可,一般不超过 3s

说干就干,打开 bili 大学搜索 argparse(argparse 这个包是我翻看 bilix 最早的 git 版本用到的,此外也可以用 click)VSCode!启动!

经过一番折腾,总算可以在本地运行了

python rimetool --input-path sample_input/vcf_sample.vcf --tool vcf

实在是太优雅了!

那我能不能做成 pip 包呢?

还是非常喜欢的 bilix,就支持 pip 安装,只要打开终端,输入 pip install bilix,就能马上使用,相比起来需要去 github 下载我的源码然后再解压才能使用,不够方便

所以我又前往 bili 大学深造,再次一番折腾,总算把 rimetool 上传到了 pypi 上,现在你也可以非常优雅地使用它

pip install rimetool

rimetool --input-path sample_input/vcf_sample.vcf --tool vcf

如何制作年轻人的第一款 pip 包

经过前面的铺垫,想必你已经大致了解如何制作一个 pip 包的流程

  • 写好源码,实现好功能
  • 增加命令行的支持
  • 制作 pip 包上传 pypi

本文篇幅有限,第一步我 python 水平有限讲不好,第二步命令行网络教程也已经比较完备,所以略过这两步。第三步的网络教程我不是很满意而且难度不高,所以这里斗胆写教程一篇

申请账号及获取密钥

首先,前往 pypi 官网申请账号(比较简单,就不赘述了)

然后在账号管理界面申请一个 api token

取一个好听的名字,选择 entire account,这个 token 的权限最高,不建议日常使用,之后成功创建项目以后可以新建一个项目专属的 token 专门用来处理本项目

保存好生成的 token 到记事本(只出现一次,关闭这个页面就不会出现了),我们来到最后一步,配置本地环境的 token

以 macOS 为例,新建一个文件$HOME/.pypirc,比如/Users/whitewatercn/.pypirc

用文本编辑器或者vim等工具编辑它,保存即可

[pypi]
  username = __token__
  password = 你上面申请到的token

接下来开始编译吧!

进入你的项目主目录,配置setup.py,这个文件里设置了诸多 pip 包相关信息,以我的为例

from setuptools import setup, find_packages

setup(
    # 以下为必需参数
    name='rimetool',  # 模块名
    version='0.1.2',  # 当前版本
    description='rime输入法相关工具',  # 简短描述
    packages=find_packages(include=['rimetool', 'rimetool.*']),  # 包含rimetool和rimetool下的所有子包
    
    # 以下均为可选参数
    long_description="rime输入法相关工具",# 长描述
    url='https://github.com/whitewatercn/rimetool', # 主页链接
    author='whitewatercn', # 作者名
    author_email='whitewatercn@outlook.com', # 作者邮箱
    classifiers=[
        'Intended Audience :: Developers', # 模块适用人群
        'Topic :: Software Development :: Build Tools', # 给模块加话题标签

    ],
    keywords=['rime','input method editor tool','python'],  # 模块的关键词,使用空格分割
    install_requires=['pypinyin',
					  'argparse',
					  'click'], # 依赖模块
    python_requires='>=3.0',  # 模块支持的Python版本
    entry_points={  # 新建终端命令并链接到模块函数
        'console_scripts': [
            'rimetool=rimetool.main:main',
        ],
        },
        project_urls={  # 项目相关的额外链接
        'Bug Reports': 'https://github.com/whitewatercn/rimetool/issues',
        'Source': 'https://github.com/whitewatercn/rimetool',
    },
)


这里面有些是必须有的,有些不必要,你可以尝试删减一些内容,特别注意的是

  • 如果你的项目里引用了自己制作的包,需要配置好 packages=find_packages(include=['rimetool', 'rimetool.*'])
  • 如果引用其他 pip 包,需要配置好install_requires=['pypinyin','argparse','click']
  • ~如果你碰到引用方面的报错,说实话我也不会,我是靠 gpt 重写解决的:dog:~

配置好后,就能在 setup.py所在的路径开始编译,在此之前你需要安装编译所需的twinewheel

pip install wheel twine

之后执行

python setup.py sdist bdist_wheel

这会在工作目录里产生很多编译文件,如果你需要上传源码到 github,记得编辑.gitignore忽略它们

(torch) (base) whitewatercn@MadBookAir rimetool % tree -L 1
.
├── LICENSE
├── README.md
├── rimetool
├── sample_input
└── setup.py

(torch) (base) whitewatercn@MadBookAir rimetool % python setup.py sdist bdist_wheel
(torch) (base) whitewatercn@MadBookAir rimetool % tree -L 1                        
.
├── LICENSE
├── README.md
├── build
├── dist
├── rimetool
├── rimetool.egg-info
├── sample_input
└── setup.py

最后上传 pypi 之前我强烈建议你先在本地运行一下,试试能不能按照你的预想跑起来

pip install -e .

通过这行命令在本地安装好你的项目,同时你对源代码的编辑可以实时更新,等你调整到满意以后,我们开始上传吧!

最后一步,上传!

将最新的源码编译后,在setup.py 的路径执行

twine upload dist/*

这将自动使用我们之前创建的$HOME/.pypirc里面的 token,不出意外的话就上传成功啦

你可以前往 pypi 官网搜一下你的项目

你也可能遇到一些问题,可以通过以下命令查看具体问题出在哪里,里面的报错非常详细

twine upload dist/* --verbose

比如我刚刚试着重新传了一次,就提醒我已经传过这个版本了File already exists.

(torch) (base) whitewatercn@MadBookAir rimetool % twine upload dist/* --verbose
INFO     Using configuration from /Users/whitewatercn/.pypirc                                                                                                                                                              
Uploading distributions to https://upload.pypi.org/legacy/
INFO     dist/rimetool-0.1.2-py3-none-any.whl (16.0 KB)                                                                                                                                                                    
INFO     dist/rimetool-0.1.2.tar.gz (16.3 KB)                                                                                                                                                                              
INFO     password set from config file                                                                                                                                                                                     
INFO     username: __token__                                                                                                                                                                                               
INFO     password: <hidden>                                                                                                                                                                                                
Uploading rimetool-0.1.2-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 20.0/20.0 kB • 00:00 • 57.1 MB/s
INFO     Response from https://upload.pypi.org/legacy/:                                                                                                                                                                    
         400 File already exists. See https://pypi.org/help/#file-name-reuse for more information.                                                                                                                         
INFO     <html>                                                                                                                                                                                                            
          <head>                                                                                                                                                                                                           
           <title>400 File already exists. See https://pypi.org/help/#file-name-reuse for more information.</title>                                                                                                        
          </head>                                                                                                                                                                                                          
          <body>                                                                                                                                                                                                           
           <h1>400 File already exists. See https://pypi.org/help/#file-name-reuse for more information.</h1>                                                                                                              
           The server could not comply with the request since it is either malformed or otherwise incorrect.<br/><br/>                                                                                                     
         File already exists. See https://pypi.org/help/#file-name-reuse for more information.                                                                                                                             
                                                                                                                                                                                                                           
                                                                                                                                                                                                                           
          </body>                                                                                                                                                                                                          
         </html>                                                                                                                                                                                                           
ERROR    HTTPError: 400 Bad Request from https://upload.pypi.org/legacy/                                                                                                                                                   
         File already exists. See https://pypi.org/help/#file-name-reuse for more information.  

根据我最近折腾的经历,最常见的是命名及版本问题

  • pip 包不可以重名
  • 新版本的setup.pyversion=''要大于过去的版本

最后

祝各位年轻人早日喜提自己的第一个 pip 包

也欢迎使用 rime 的朋友使用 & 完善 rimetool

相关链接

rimetool——一些 rime 相关工具

rime_clinic——rime 中英文医学词库

深蓝词库转换

雾凇拼音——rime 长期维护的简体词库