上次写的一个终端里面斗鱼TV弹幕Python版本和Ruby版本,并且发布到PIP和RubyGems上面.在发布PIP包的时候,居然Google不到一篇可以非常好的讲解这个流程的文章.于是整理这篇文章,并且方便后来自己检索,并且方便他人找资料.
自推荐下依照本文定制的命令行工具danmu.fm的github地址:
https://github.com/twocucao/danmu.fm
本文的目的也是非常简单:
写一个Python命令行工具,并且发布到PIP上面.并且在这个过程中给出我自己的一些思考.
只需要进行如下的两个步骤便可以:
当然,这样不够细致.再细分一下.
写好一个命令行工具首先要知道命令行工具是什么?
在我看来,命令行工具就是一种完成某种类型的任务的终端程序.
也就是基本上没有什么用户界面的程序.
由于基本上没有什么用户界面,所以导致单个命令行的交互能力及其低下.但这种低下的交互性对于一些固定工作而言,简直就是最灵活的工具.只需要输入一些命令便可以完成某种类型的工作.实在是方便的很.
所以,某种程度上,终端程序低交互的缺点反而成了优点.
对于Python和命令行交互,我们很容易想出一个比较方便的方案.
sys.argv就是这样的嘛!
我们很容易这样写代码.
1
|
python
testargv
.
py
thisisaargv1
|
甚至我们也可以这样写命令行,
1
|
python
testargv
.
py
thisisaargv1
-
d
-
f
0
|
那么,这样写的后果就是,不方便解析出(不是不能,是不方便) -d -f 0 以及 thisisaargv1.
不信的话,你解析一个下面场景的命令行试试,
1
2
3
4
|
# 用户可能这样输入
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.
上面的描述就变成了这个样子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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
这样就可以执行命令
1
|
python
danmu
.
py
http
:
//www.douyutv.com/xiaocang -q 1 -v 2
|
通过args就可以获取参数,然后进行终端程序的参数初始化.
可是这和我们的要求还是不同嘛,我们不想多写Python XXX,我们想直接XXX.就像这样.
1
|
danmu
.
fm
-
q
1
-
v
2
http
:
//www.douyutv.com/xiaocang
|
不急,下面就是了.
于是,现在就要开始组织代码结构了.
我们在最终的代码目录大概是这样的.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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的代码目录.
聪明的你这时候你注意到了:
对于上面几点,我们分别进行解释
为了把主要的程序分离出来,放在第二目录下面,这样的待会打包以后多出很多文件夹就不会对源码造成干扰.
当然,由于把程序放在了第二目录下面,所以,脚本里面的from import语句应该使用相对路径导入.
相对路径导入的的时候需要注意运行的时候使用如下命令
1
|
python3
-
m
danmufm
.
danmu
[
xxxx
]
|
填写如下内容即可.
1
2
|
[
metadata
]
description
-
file
=
README
.
md
|
然后去写Markdown的Readme就好了.
这个是重头戏了.
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
|
#-*- 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'
,
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可以添加依赖.其他的你猜都可以猜出来是做什么的.自己去看代码,我就不多说了.
所谓的发布,就是将打包好的程序的某个版本发布到某个仓库中.
到这个上面注册账号:
https://pypi.python.org/pypi
进入对应项目根文件,然后执行
1
|
python3
setup
.
py
register
|
这一步程序会让你输入刚刚注册的账号和密码,然后注册该包.注册该包以后,你就有了一个小仓库.可以存放不同版本的danmu.fm.
注册的仓库是可以在这个地址看到的,
https://pypi.python.org/pypi?%3Aaction=pkg_edit&name=danmu.fm
这里需要借助一个小工具,twine.twine是一个更加安全方便上传打包好的代码的工具.
1
|
pip3
install
twine
|
接着开始打包,打包成两个版本,一个是不需要build的版本,另一个是需要build的版本(顺带吐槽下,这两个诡异的命名).
1
|
python
setup
.
py
sdist
bdist_wheel
|
于是剩下来的就显而易见了,上传build完毕的程序到仓库中.
1
|
twine
upload
dist
/
danmu
.
fm
-
0.1.2
*
|
于是,安装一下,测试是否成功
1
|
pip3
install
danmu
.
fm
--
upgrade
|
命令行的工具是这样使用的.
1
|
danmu
.
fm
-
q
2
-
v
1
http
:
//www.douyutv.com/16789
|
不断的完善代码,然后打包终端程序发布到仓库给别人用,这就是整个的PIP打包发布流程.