如何发布一个Python命令行工具

本文简介

上次写的一个终端里面斗鱼TV弹幕Python版本和Ruby版本,并且发布到PIP和RubyGems上面.在发布PIP包的时候,居然Google不到一篇可以非常好的讲解这个流程的文章.于是整理这篇文章,并且方便后来自己检索,并且方便他人找资料.

自推荐下依照本文定制的命令行工具danmu.fm的github地址:

https://github.com/twocucao/danmu.fm

本文的目的也是非常简单:

写一个Python命令行工具,并且发布到PIP上面.并且在这个过程中给出我自己的一些思考.

如何分解这个发布任务?

只需要进行如下的两个步骤便可以:

  • 1.写好一个Python命令行工具.
  • 2.发布它.

当然,这样不够细致.再细分一下.

  • 1.写好一个Python命令行工具
    • 1.1.命令行的特点,以及Python的如何编写命令行
    • 1.2.如何组织代码结构.
  • 2.发布
  • 2.1.注册pypi账户
    • 2.2.注册在账户下面注册Python包
    • 2.3.上传打包好的Python命令行工具.
  • 3.完善代码

1.写好一个Python命令行工具

写好一个命令行工具首先要知道命令行工具是什么?

在我看来,命令行工具就是一种完成某种类型的任务的终端程序.

也就是基本上没有什么用户界面的程序.

由于基本上没有什么用户界面,所以导致单个命令行的交互能力及其低下.但这种低下的交互性对于一些固定工作而言,简直就是最灵活的工具.只需要输入一些命令便可以完成某种类型的工作.实在是方便的很.

所以,某种程度上,终端程序低交互的缺点反而成了优点.

1.1.Python的如何编写一个简单的命令行

对于Python和命令行交互,我们很容易想出一个比较方便的方案.

sys.argv就是这样的嘛!

我们很容易这样写代码.

 python testargv.py thisisaargv1

甚至我们也可以这样写命令行,

 python testargv.py thisisaargv1 -d -f 0 

那么,这样写的后果就是,不方便解析出(不是不能,是不方便) -d -f 0 以及 thisisaargv1.

不信的话,你解析一个下面场景的命令行试试,

# 用户可能这样输入
danmu.fm http://www.douyutv.com/xiaocang -q 1 -v 2 
danmu.fm -q 1 -v 2 http://www.douyutv.com/xiaocang
# 当然,肯定还有漏写啦,等等,你得需要转类型,增加各种blablabla的描述吧,添加默认的参数值吧.

于是Python就提供了一个非常好用的模块可以使用.叫做argparse.

上面的描述就变成了这个样子

import argparse

APP_DESC="""
这就是描述
"""
print(APP_DESC)
if len(sys.argv) == 1:
    sys.argv.append('--help')
parser = argparse.ArgumentParser()
parser.add_argument('-q','--quality',type=int,default=0,help="download video quality : 1 for the standard-definition; 3 for the super-definition")
parser.add_argument('-v','--verbose', default=0,help="print more debuging information")
parser.add_argument('-s','--store',help="保存流媒体文件到指定位置")
parser.add_argument('-c','--config',default=0,help="读取~/.danmu.fm配置,请~/.danmu.fm指定数据库")
parser.add_argument('url',metavar='URL',nargs='+', help="zhubo page URL (http://www.douyutv.com/*/)")
args = parser.parse_args()
# 获取对应参数只需要args.quality,args.url之类.
url = (args.url)[0]
print(url)
#其他执行逻辑

保存为danmu.py

这样就可以执行命令

python danmu.py http://www.douyutv.com/xiaocang -q 1 -v 2

通过args就可以获取参数,然后进行终端程序的参数初始化.

可是这和我们的要求还是不同嘛,我们不想多写Python XXX,我们想直接XXX.就像这样.

danmu.fm -q 1 -v 2 http://www.douyutv.com/xiaocang

不急,下面就是了.

1.2.如何组织代码结构.

于是,现在就要开始组织代码结构了.

我们在最终的代码目录大概是这样的.

danmu.fm
├── README.md
├── danmufm
│   ├── __init__.py
│   ├── client
│   │   ├── __init__.py
│   │   ├── __init__.pyc
│   │   ├── douyu_client.py
│   │   └── douyu_danmu_client.py
│   ├── danmu.py
│   ├── misc
│   │   ├── __init__.py
│   │   ├── color_printer.py
│   │   ├── downloaders.py
│   │   └── player.py
│   └── model
│       ├── __init__.py
│       └── douyu_msg.py
├── docs
├── setup.cfg
├── setup.py
├── sh.py
└── tests

这就是我上次写的danmu.fm的代码目录.

聪明的你这时候你注意到了:

  1. 主要的程序不是放在根目录下面,而是放在第二目录danmufm下面.
    2.setup.cfg 是什么鬼东西
    3.setup.py 是什么鬼东西

对于上面几点,我们分别进行解释

1.2.1 为什么主要程序在第二目录下

为了把主要的程序分离出来,放在第二目录下面,这样的待会打包以后多出很多文件夹就不会对源码造成干扰.

当然,由于把程序放在了第二目录下面,所以,脚本里面的from import语句应该使用相对路径导入.

相对路径导入的的时候需要注意运行的时候使用如下命令

python3 -m danmufm.danmu [xxxx]

1.2.2 setup.cfg

填写如下内容即可.

[metadata]
description-file = README.md

然后去写Markdown的Readme就好了.

1.2.3 setup.py

这个是重头戏了.

setup这个py文件就是打包配置文件.对这个程序是谁的,有什么依赖,入口是什么,等等等等的配置.


#-*- encoding: UTF-8 -*-
from setuptools import setup, find_packages
"""
打包的用的setup必须引入,
"""

VERSION = '0.1.1'

setup(name='danmu.fm',
      version=VERSION,
      description="a tiny and smart cli player of douyutv,ximalayad,anmu based on Python",
      long_description='just enjoy',
      classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
      keywords='python douyu danmu danmu.fm terminal',
      author='twocucao',
      author_email='twocucao@gmail.com',
      url='https://github.com/twocucao/doumu.fm',
      license='MIT',
      packages=find_packages(),
      include_package_data=True,
      zip_safe=True,
      install_requires=[
        'requests',
      ],
      entry_points={
        'console_scripts':[
            'danmu.fm = danmufm.danmu:main'
        ]
      },
)

官方有distutils这个包管理器工具,设置也非常的简单,只是,它不支持entry_points属性,由于无法使用entry_point,也就无法通过命令来跳转到指定模块运行程序,这也就意味着,官方工具不方便写成命令行.还是setuptools好.

上面需要注意的就是install_requires可以添加依赖.其他的你猜都可以猜出来是做什么的.自己去看代码,我就不多说了.

2.发布

所谓的发布,就是将打包好的程序的某个版本发布到某个仓库中.

2.1.注册pypi账户

到这个上面注册账号:
https://pypi.python.org/pypi

2.2.注册在账户下面注册Python包

进入对应项目根文件,然后执行

python3 setup.py register

这一步程序会让你输入刚刚注册的账号和密码,然后注册该包.注册该包以后,你就有了一个小仓库.可以存放不同版本的danmu.fm.

注册的仓库是可以在这个地址看到的,
https://pypi.python.org/pypi?%3Aaction=pkg_edit&name=danmu.fm

2.3.上传打包好的Python命令行工具.

这里需要借助一个小工具,twine.twine是一个更加安全方便上传打包好的代码的工具.

pip3 install twine

接着开始打包,打包成两个版本,一个是不需要build的版本,另一个是需要build的版本(顺带吐槽下,这两个诡异的命名).

python setup.py sdist bdist_wheel

于是剩下来的就显而易见了,上传build完毕的程序到仓库中.

twine upload dist/danmu.fm-0.1.2*

于是,安装一下,测试是否成功

pip3 install danmu.fm --upgrade

命令行的工具是这样使用的.

danmu.fm -q 2 -v 1 http://www.douyutv.com/16789

3.完善

不断的完善代码,然后打包终端程序发布到仓库给别人用,这就是整个的PIP打包发布流程.

  • 这个时候,你可能需要使用版本控制软件.
  • 你可能需要增多的代码的测试.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容