持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
1、前言
我们在日常工作中,可能会用到很多的命令,比如获取IP、查看时间等等。但是频繁的切换不同的命令是不优雅的,为了方便我们决定做一个命令行小工具,将讲这些功能集成进来。之前我们已经介绍过fire开发命令行工具,今天我们就介绍一款新的命令行工具框架typer。
2、快速开始
2.1、安装typer
pip install typer
2.2、入门Demo
import typer
def main(name: str):
typer.echo(f"Hello {name}")
if __name__ == "__main__":
typer.run(main)
执行代码:
E:\demo\demo\test>python demo.py
Usage: demo.py [OPTIONS] NAME
Try 'demo.py --help' for help.
Error: Missing argument 'NAME'.
E:\demo\demo\test>python demo.py phyger
Hello phyger
如上,首先main方法需要一个参数name对应命令行的必选参数,如果不带参数执行命令或者执行python demo.py --help
,typer都会向我们提示错误原因。然后,当我们携带了正确的参数后,就能够拿到预期的结果。即将函数命令行化。
2.3、进阶Demo
以上只有一个函数,不适合扩展和实际使用。我们可以使用如下方式开发一个多命令的工具。
import typer
import time
# 实例化typer
app = typer.Typer()
# 使用app.command()装饰器将函数变为命令
@app.command()
def date():
res = time.localtime()
ret = time.strftime('%Y-%m-%d %H:%M:%S', res)
typer.echo(f"Now: {ret}")
@app.command()
def goodbye(name: str, formal: bool = False):
if formal:
typer.echo(f"Goodbye Ms. {name}. Have a good day.")
else:
typer.echo(f"Bye {name}!")
if __name__ == "__main__":
app()
如上,我们可以执行命令python demo.py date
获取当前时间,执行python demo.py goodbye phyger
打印Bye phyger
,执行python demo.py goodbye --formal
打印Goodbye Ms. phyger. Have a good day.
。
E:\demo\demo\test>python demo.py date
Now: 2022-06-23 16:05:41
E:\demo\demo\test>python demo.py goodbye phyger
Bye phyger!
E:\demo\demo\test>python demo.py goodbye phyger --formal
Goodbye Ms. phyger. Have a good day.
2.4、给点颜色
有时候,在特殊的场景下,我们为了更易于观察,我们可能会给命令行的输出结果加上颜色,就像下面这样:
import typer
import time
# 实例化typer
app = typer.Typer()
# 使用app.command()装饰器将函数变为命令
@app.command()
def goodbye(name: str, formal: bool = False):
if formal:
typer.secho(f"Goodbye Ms. {name}. Have a good day.",fg=typer.colors.MAGENTA)
else:
typer.secho(f"Bye {name}!",fg=typer.colors.RED)
if __name__ == "__main__":
app()
如上代码执行结果:
2.5、异常处理
当我们代码在接受到不符合预期的数据时,或者命令行处理过程中发生异常时,我们可以使用typer的Exit和Abort方法进行处理。
import typer
import time
# 实例化typer
app = typer.Typer()
@app.command()
def jj(j: int):
if j > 60:
typer.secho('too big!', fg=typer.colors.RED)
raise typer.Abort()
if j < 18:
typer.secho('too small!', fg=typer.colors.YELLOW)
raise typer.Exit(400)
else:
typer.secho('success!', fg=typer.colors.GREEN)
if __name__ == "__main__":
app()
以上代码执行结果:
E:\demo\demo\test>python demo.py jj 4
too small!
E:\demo\demo\test>python demo.py jj 70
too big!
Aborted!
E:\demo\demo\test>python demo.py jj 56
success!
可以见到Exit没有任何打印,只是退出命令行;而Abort有打印提示。
2.6、可选参数和默认参数
在命令行中,当某些参数不是必须的时候我们就需要用到可选参数;当某些参数的值很少变化时,我们就需要用到默认参数了。
import typer
import time
# 实例化typer
app = typer.Typer()
from typing import Optional
@app.command()
def opt(name: str, age: Optional[int]=0):
'''
@age:是可选参数,并且有默认值
'''
if age<=0:
typer.secho(f"Hi {name}!", fg=typer.colors.MAGENTA)
else:
typer.secho(f"Hi {name}, your age is {age}", fg=typer.colors.RED)
if __name__ == "__main__":
app()
代码执行结果:
E:\demo\demo\test>python demo.py opt phyger
Hi phyger!
E:\demo\demo\test>python demo.py opt phyger --age 17
Hi phyger, your age is 17
E:\demo\demo\test>python demo.py opt phyger --help
Usage: demo.py opt [OPTIONS] NAME
@age:是可选参数,并且有默认值
Arguments:
NAME [required]
Options:
--age INTEGER [default: 0]
--help Show this message and exit.
如上,代码中的注释也会被typer当做命令行注释在help中打印出来。
2.7、交互式
某些时候,我们需要和用户交互,从用户输入获取一些数据,这个时候就需要用到typer的交互式功能。
import typer
import time
# 实例化typer
app = typer.Typer()
@app.command()
def jh():
age = typer.prompt('请输入你的年龄:',type=int)
if age<18:
typer.echo(f"少年,你的年龄是:{age}!")
elif age<30:
typer.echo(f"青年,你的年龄是:{age}!")
elif age<50:
typer.echo(f"中年,你的年龄是:{age}!")
elif age<70:
typer.echo(f"老年,你的年龄是:{age}!")
else:
typer.echo(f"老老年,你的年龄是:{age}!")
if __name__ == "__main__":
app()
以上代码执行结果:
E:\demo\demo\test>python demo.py jh
请输入你的年龄:: 5
少年,你的年龄是:5!
E:\demo\demo\test>python demo.py jh
请输入你的年龄:: 18
青年,你的年龄是:18!
E:\demo\demo\test>python demo.py jh
请输入你的年龄:: 35
中年,你的年龄是:35!
E:\demo\demo\test>python demo.py jh
请输入你的年龄:: 79
老老年,你的年龄是:79!
当我们需要输入密码的时候,我们可以将输入的字符隐藏,在typer.prompt
中打开hide_input=True
即可。
2.8、进度条
当我们进行一些耗时的任务时,我们可能需要向用户展示进度条以增加好感和提高可观测性。
import typer
import time
# 实例化typer
app = typer.Typer()
@app.command()
def fkbar(num:int):
with typer.progressbar(range(num)) as bar:
for i in bar:
time.sleep(0.1) # 模拟任务处理
#typer.echo(i)
typer.echo('done!')
if __name__ == "__main__":
app()
以上代码执行结果:
E:\demo\django-demo\test>python demo.py fkbar 10
[####################################] 100%
done!
2.9、打开浏览器
这是typer的独特功能。
@app.command()
def openB():
typer.echo('ready to open browser!')
typer.launch('https://u1s1.vip')
以上代码即可打开:u1s1.vip