新手向——用python编写命令行应用的简洁方式

The easy (and nice) way to do CLI apps in Python——github源码 为一个简单的python命令行应用的基本结构。

我们有一些方法可以做出Python命令行式app。我试过它们,不过它们大都有自己的痛点和烦恼。所以我到社区里去寻找一种更好的方法。

什么是CLI?

CLI 意味着命令行界面(command line interface)。它是一类用命令行/终端调用的app。作为开发人员,更是一个少用鼠标,多用键盘党,我一直使用CLI应用。当我需要一些为自己服务的定制软件时,CLI就能满足我的需求,而python是一门能够快速生产CLI应用的伟大语言。

文件系统结构

pycli/
├── README.md
├── install.sh
├── pycli
  ├── __init__.py
  ├── __main__.py
  ├── classmodule.py
  └── funcmodule.py
└── setup.py

正如你所见,该项目的根目录被我命名为pycli。该应用也将在setup.py中被设置为以名称pycli被调用。

CLI子目录

在该CLI根目录下只有一个子目录。它的名字和CLI应用同名,但是在更复杂的CLI应用中,你需要有多个包。每个子目录是每个包的容器。在我的简单案例中,只有单个包,也就是单个子目录。

__init__.py

这个文件(文件)放在这里是告诉Python这个目录是一个包。它可以是空的,只是做个关于包的简单提示;也可以包含实际代码,在包自身初始化时会被运行

__main__.py

这是重要部分,是我们CLI应用的入口,根目录下的setup.py中的安装配置会指示它。这里只是放些简单的代码在这里表明它起作用了。

import sys
from .classmodule import MyClass
from .funcmodule import my_function
def main(): 
# 以下内容中的参数解析方式并不好,这里只是为了简单
# 最好使用argparse或者click模块做这方面的工具
    print('in main')
    args = sys.argv[1:]
    print('count of args :: {}'.format(len(args)))
    for arg in args:
        print('passed argument :: {}'.format(arg))
    my_function('hello world')
    my_object = MyClass('Thomas')
    my_object.say_name()
#以下无关于包安装,只是为了本文件的测试
if __name__ == '__main__':
    main()

上面所做的只是引入一些其它模块,分析被传入CLI的命令行参数,然后使用导入模块的成员(一个简单的函数和一个简单的类)。

classmodule.py

一个被导入__main__.py并被实例化的极简的类(也没啥用)。这里是为了说明如何从同一个包里的其它模块中引入一个类

class MyClass():
    def __init__(self, name):
        self.name = name
    def say_name(self):
        print('name is {}'.format(self.name))

funcmodule.py

classmodule.py展示如何为__main__.py定义一个可以导入的类,funcmodule.py展示了如何定义一个简单的函数让__main__.py导入并调用

def my_function(text_to_display):
    print('text from my_function :: {}'.format(text_to_display))

setup.py

现在让我们回到CLI源码的根目录。setup.py文件将所有东西联系在一起并告诉Python如何处理它们

from setuptools import setup
setup(
    name = 'pycli',
    version = '0.1.0',
    packages = ['pycli'],
    entry_points = {
        'console_scripts': [
            'pycli = pycli.__main__:main'
        ]
    })

第一眼看上去可能觉得很复杂。但是全部工作只是从setuptools库导入setup函数,并传入一些参数来调用它。其中大部分是不言自明的。packages参数是根目录下所有包的列表。
entry_points是重要部分。它用字符串表明当前应用该以什么名称被调用,以及被运行时真正调用的是什么。这里写的是pycli = pycli.__main__:main,也就是说,该应用被叫做pycli,当执行该应用时它会调用pycli包下的__main__模块的main函数。就是这样!

install.sh

安装你的Python CLI应用的最佳方式是使用pip(python3则是pip3)。在CLI源码的根目录下运行pip3 install . 将会使用setup.py作为"指令"安装这个应用,同样,使用pip3 uninstall pycli卸载这个应用。

写在脚本中即是

pip3 uninstall pycli -y  # 标签-y意味着确认卸载
pip3 install .

这样会安装到python Lib的site-packages中,或者更简洁的是

pip3 install -e .

这样是在当前根目录下生成了egg-info文件,而在site-packages文件夹中生成一个egg-link链接,如下图


这样,就可以直接运行install.sh以现有的CLI源码来更新原来的CLI应用了。

总结

掌握了简单的流程,用python编写命令行程序是简洁高效的。使用结果如首图

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

推荐阅读更多精彩内容

  • Python 面向对象Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对...
    顺毛阅读 4,207评论 4 16
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • 22年12月更新:个人网站关停,如果仍旧对旧教程有兴趣参考 Github 的markdown内容[https://...
    tangyefei阅读 35,159评论 22 257
  • 你本来有平滑的肌肤 奈何 所有的记忆变成了岁月的纹 在你身上一点点浮现 我摸着你的坎坷 心都在颤抖 许久之后你会不...
    静羽明海阅读 164评论 0 11
  • (三)札幌 这是北海道之旅的第二篇,有关札幌。 我们在函馆逗留了两个晚上,第三天上午,便坐了JR往札幌。 到达的时...
    Ivy的长街阅读 546评论 6 2