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

作者: 无与童比 | 来源:发表于2016-02-21 20:30 被阅读5396次

    本文简介

    上次写的一个终端里面斗鱼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打包发布流程.

    • 这个时候,你可能需要使用版本控制软件.
    • 你可能需要增多的代码的测试.

    相关文章

      网友评论

      • bigCatloveFish:大神 我模仿你的目录写了一下。但是 上传之后 运行的时候 却是 zsh: command not found:。能赐教一下么?
      • ae883cbf3415:博主你好,感谢你写的内容,非常的清晰易懂。有一个小小的问题,如果说不想通过pip的方式来安装,而是通过下载源码的方式,请问如何安装?这样做也可以直接使用damu.fm命令执行么?(不用敲python)
        ae883cbf3415:@无与童比 嗯嗯,thx!
        无与童比:@虞欣言 哦哦,你也可以用pip本地安装然后用命令即可
        无与童比:@虞欣言 下载源码就直接用源码启动的方式呀。
      • 碧海情天:没往下看,单冲前面内容透露的态度和基础,在目前的简书己经显得难得了(虽然这实在令人感觉不足),鼓励一下。
        无与童比: @碧海情天 谢谢
      • 楼上那位:给你点赞
        无与童比: @楼外楼的春天 谢谢
      • 泰克尼客:好东西,赞一个

      本文标题:如何发布一个Python命令行工具

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