展开菜单
首页 精品内容 本月促销 装机必备 Windows macOS软件 IOS软件 Android AI PDF教程 专题
全部分类

当前位置:

首页 > 编程开发 > 如何使用click库创建完美的Python命令行程序?

如何使用click库创建完美的Python命令行程序?

Python程序员的主要工作是写命令行程序,即直接在终端运行的脚本。随着项目规模增长,我们希望创建有效的命令行接口,通过提供不同的参数,解决不同的问题,而不是每次都修改源代码。为了实现这一目标,我总结了四条原则,希望对大家有所帮助:命令行参数应提供默认值处理所有可能的参数错误,包括缺少参数,数据类型错误,无法找到文件等撰写完善的文档,解释参数的含义以及如何设置使用进度条显示长时间运行的任务一个简单的例子让我们将这些规则应用于一个具体的案例:一个使用Caesarcipher加密和解密消息的脚本。

如何使用click库创建完美的Python命令行程序?


Python程序员的主要工作是写命令行程序,即直接在终端运行的脚本。随着项目规模增长,我们希望创建有效的命令行接口,通过提供不同的参数,解决不同的问题,而不是每次都修改源代码。

为了实现这一目标,我总结了四条原则,希望对大家有所帮助:

  • 命令行参数应提供默认值
  • 处理所有可能的参数错误,包括缺少参数,数据类型错误,无法找到文件等
  • 撰写完善的文档,解释参数的含义以及如何设置
  • 使用进度条显示长时间运行的任务

一个简单的例子

让我们将这些规则应用于一个具体的案例:一个使用Caesar cipher加密和解密消息的脚本。

假设我们编写了一个encrypt函数,如下所示。现在要创建一个的脚本来加密和解密消息。

脚本允许用户选择:模式(加密或解密),密钥。前者的默认值是加密,后者的默认值是1。这一切都通过命令行参数实现。

def encrypt(plaintext, key):
cyphertext = ''
for character in plaintext:
if character.isalpha():
number = ord(character)
number += key
if character.isupper():
if number > ord('Z'):
number -= 26
elif number < ord('A'):
number += 26
elif character.islower():
if number > ord('z'):
number -= 26
elif number < ord('a'):
number += 26
character = chr(number)
cyphertext += character
return cyphertext

初学者方法:sys.argv

脚本需要先获取命令行参数的值,让我们先用最简单的sys.argv实现。

sys.argv是一个列表,包含了用户在运行脚本时输入的所有参数(包括脚本名字本身)。

在终端输入以下指令:

> python caesar_script.py --key 23 --decrypt my secret message
pb vhfuhw phvvdjh

sys.argv列表包括:

['caesar_script.py', '--key', '23', '--decrypt', 'my', 'secret', 'message']

为了获得参数值,需要遍历参数列表,寻找一个 '--key' (或 '-k' )来获取密钥值,并寻找一个 '--decrypt' 获取模式。

import sys
from caesar_encryption import encryp
def caesar():
key = 1
is_error = False
for index, arg in enumerate(sys.argv):
if arg in ['--key', '-k'] and len(sys.argv) > index + 1:
key = int(sys.argv[index + 1])
del sys.argv[index]
del sys.argv[index]
break
for index, arg in enumerate(sys.argv):
if arg in ['--encrypt', '-e']:
del sys.argv[index]
break
if arg in ['--decrypt', '-d']:
key = -key
del sys.argv[index]
break
if len(sys.argv) == 1:
is_error = True
else:
for arg in sys.argv:
if arg.startswith('-'):
is_error = True
if is_error:
print(f'Usage: python {sys.argv[0]} [ --key  ] [ --encrypt|decrypt ] ')
else:
print(encrypt(' '.join(sys.argv[1:]), key))
if __name__ == '__main__':
caesar()

代码遵循我们一开始提出的原则:

有一个默认键值和一个默认模式

处理基本错误(不提供输入文本或未知参数)

在参数错误或在不带参数的情况下调用脚本时,打印简洁的提示信息

> python caesar_script_using_sys_argv.py
Usage: python caesar.py [ --key  ] [ --encrypt|decrypt ] 

但是这个版本的脚本相当长(39行,不包括加密函数),而且代码非常丑陋。

是否有更好的方法来解析命令行参数?

进入argparse

argparse是用于解析命令行参数的Python标准库模块。

修改脚本,使用argparse解析命令行参数:

import argparse
from caesar_encryption import encrypt
def caesar():
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('-e', '--encrypt', action='store_true')
group.add_argument('-d', '--decrypt', action='store_true')
parser.add_argument('text', nargs='*')
parser.add_argument('-k', '--key', type=int, default=1)
args = parser.parse_args()
text_string = ' '.join(args.text)
key = args.key
if args.decrypt:
key = -key
cyphertext = encrypt(text_string, key)
print(cyphertext)
if __name__ == '__main__':
caesar()

代码仍然遵守我们提出的原则,并且比手动解析命令行参数提供更精确的文档和更具交互性的错误处理。

> python caesar_script_using_argparse.py --encode My message
usage: caesar_script_using_argparse.py [-h] [-e | -d] [-k KEY] [text [text ...]]
caesar_script_using_argparse.py: error: unrecognized arguments: --encode
> python caesar_script_using_argparse.py --help
usage: caesar_script_using_argparse.py [-h] [-e | -d] [-k KEY] [text [text ...]]positional arguments:
text
optional arguments:
-h, --help show this help message and exit
-e, --encrypt
-d, --decrypt
-k KEY, --key KEY

脚本的第7行到第13行代码定义了命令行参数,但它们不是很优雅:太冗长且程序化,我们可以用更紧凑和声明性的方式完成。

使用click创建更好的命令行接口

幸运的是有一个三方库click用于创建命令行接口,它不仅提供比argparse更多的功能, 而且代码风格更漂亮。用click替换argparse,继续优化脚本。

import click
from caesar_encryption import encrypt
@click.command()
@click.argument('text', nargs=-1)
@click.option('--decrypt/--encrypt', '-d/-e')
@click.option('--key', '-k', default=1)
def caesar(text, decrypt, key):
text_string = ' '.join(text)
if decrypt:
key = -key
cyphertext = encrypt(text_string, key)
click.echo(cyphertext)
if __name__ == '__main__':
caesar()

注意,命令行参数和选项都在装饰器中声明, 这使得它们可以作为函数的参数直接访问。

让我们仔细分析上面的代码:

nargs定义了命令行参数接收的值的数量,默认值为1,nargs=-1允许提供任意数量的单词。

--encrypt/--decrypt定义互斥的选项 ,最终以布尔值传递给程序。

click.echo是click库提供的基础函数,功能类似于print,但提供更强大的功能,例如调整打印到控制台的文本的颜色。

从本地文件读取输入

命令行参数接收的值是将被加密的最高机密消息,所以如果要求用户直接在终端中输入纯文本,可能会引发安全顾虑。

一种更安全的方法是使用隐藏提示,或者从本地文件读取文本 ,这对于长文本来说更加实用。

这个想法同样适用于输出:用户可以将其保存到文件中,或者在终端中打印出来。让我们继续优化脚本。

import click
from caesar_encryption import encrypt
@click.command()
@click.option(
'--input_file',
type=click.File('r'),
help='File in which there is the text you want to encrypt/decrypt.'
 'If not provided, a prompt will allow you to type the input text.',
)
@click.option(
'--output_file',
type=click.File('w'),
help='File in which the encrypted / decrypted text will be written.'
 'If not provided, the output text will just be printed.',
)
@click.option(
'--decrypt/--encrypt',
'-d/-e',
help='Whether you want to encrypt the input text or decrypt it.'
)
@click.option(
'--key',
'-k',
default=1,
help='The numeric key to use for the caesar encryption / decryption.'
)
def caesar(input_file, output_file, decrypt, key):
if input_file:
text = input_file.read()
else:
text = click.prompt('Enter a text', hide_input=not decrypt)
if decrypt:
key = -key
cyphertext = encrypt(text, key)
if output_file:
output_file.write(cyphertext)
else:
click.echo(cyphertext)
if __name__ == '__main__':
caesar()

由于脚本变得更复杂,我们创建了参数文档(通过定义click.option装饰器的help参数实现),详细解释参数的功能,效果如下。

> python caesar_script_v2.py --help
Usage: caesar_script_v2.py [OPTIONS]
Options:
--input_file FILENAMEFile in which there is the text you want to encrypt/decrypt. If not provided, a prompt will allow you to type the input text.
--output_file FILENAME File in which the encrypted/decrypted text will be written. If not provided, the output text will just be printed.
-d, --decrypt / -e, --encryptWhether you want to encrypt the input text or decrypt it.
-k, --key INTEGERThe numeric key to use for the caesar encryption / decryption.
--help Show this message and exit.

我们有两个新的参数input_file和output_file,类型是click.File,click会用正确的模式打开文件并处理可能发生的错误。例如找不到文件:

> python caesar_script_v2.py --decrypt --input_file wrong_file.txt
Usage: caesar_script_v2.py [OPTIONS]
Error: Invalid value for "--input_file": Could not open file: wrong_file.txt: No such file or directory

如果未提供input_file,则我们用click.prompt,在命令行创建提示窗口,让用户直接输入文本,该提示对于加密模式将是隐藏的。效果如下:

> python caesar_script_v2.py --encrypt --key 2
Enter a text: **************
yyy.ukectc.eqo

假设你是一名黑客:想要解密一个用凯撒加密过的密文,但你不知道秘钥是什么。最简单的策略就是用所有可能的秘钥调用解密函数 25 次,阅读解密结果,看看哪个是合理的。但你很聪明,而且也很懒,所以你想让整个过程自动化。确定解密后的 25 个文本哪个最可能是原始文本的方法之一,就是统计所有这些文本中的英文单词的个数。这可以使用 PyEnchant 模块实现:

import click
import enchant
from caesar_encryption import encrypt
@click.command()
@click.option(
'--input_file',
type=click.File('r'),
required=True,
)
@click.option(
'--output_file',
type=click.File('w'),
required=True,
)
def caesar_breaker(input_file, output_file):
cyphertext = input_file.read()
english_dictionnary = enchant.Dict("en_US")
max_number_of_english_words = 0
for key in range(26):
plaintext = encrypt(cyphertext, -key)
number_of_english_words = 0
for word in plaintext.split(' '):
if word and english_dictionnary.check(word):
number_of_english_words += 1
if number_of_english_words > max_number_of_english_words:
max_number_of_english_words = number_of_english_words
best_plaintext = plaintext
best_key = key
click.echo(f'The most likely encryption key is {best_key}. It gives the following plaintext:nn{best_plaintext[:1000]}...')
output_file.write(best_plaintext)
if __name__ == '__main__':
caesar_breaker()

如何使用click库创建完美的Python命令行程序?

使用进度条

示例中的文本包含10^4个单词,因此该脚本需要大约5秒才能解密。这很正常,因为它需要检查所有25个秘钥,每个秘钥都要检查10^4个单词是否出现在英文字典中。

假设你要解密的文本包括10^5个单词,那么就要花费50秒才能输出结果,用户可能会非常着急。因此我建议这种任务一定要显示进度条。特别是,显示进度条还非常容易实现。下面是个显示进度条的例子:

import click
import enchant
from tqdm import tqdm
from caesar_encryption import encrypt
@click.command()
@click.option(
'--input_file',
type=click.File('r'),
required=True,
)
@click.option(
'--output_file',
type=click.File('w'),
required=True,
)
def caesar_breaker(input_file, output_file):
cyphertext = input_file.read()
english_dictionnary = enchant.Dict("en_US")
best_number_of_english_words = 0
for key in tqdm(range(26)):
plaintext = encrypt(cyphertext, -key)
number_of_english_words = 0
for word in plaintext.split(' '):
if word and english_dictionnary.check(word):
number_of_english_words += 1
if number_of_english_words > best_number_of_english_words:
best_number_of_english_words = number_of_english_words
best_plaintext = plaintext
best_key = key
click.echo(f'The most likely encryption key is {best_key}. It gives the following plaintext:nn{best_plaintext[:1000]}...')
output_file.write(best_plaintext)
if __name__ == '__main__':
caesar_breaker()

这里使用了tqdm库,tqdm.tqdm类可以将任何可迭代对象转化为一个进度条。click也提供了类似的接口来创建进度条(click.progress_bar),但我觉得它不如tqdm好用。

如何使用click库创建完美的Python命令行程序?

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
编程开发 命令行 Python
相关文章 更多
精品专题 更多
本月促销

正软商城本月促销专区,汇集办公、设计、安全、影音、系统工具及AI软件等正版软件优惠活动,提供限时折扣、特价授权和优惠购买信息,活动库存及价格以页面实时展示为准。

装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

IOS软件

正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

AI

正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
灵活计算器
灵活计算器

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

图几
图几

图几是一款适用于 macOS 的截图、标注与美化工具,支持离线操作保障隐私。界面整理和高频系统操作被放到一起考虑,桌面或窗口内容一多时,管理起来会更省心。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Menuist
Menuist

Menuist 是一款面向 macOS 的 Finder 右键菜单增强工具,主要用来补充新建文件、快捷导航等常用操作,让日常文件管理和访问路径时更高效、更顺手。

Mole
Mole

Mole 是一款专为 Mac 设计的深度清理优化工具,涵盖缓存清理、应用管理及实时状态监控等功能。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

WINDOWS 更多
Windows 10
Windows 10

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

傲梅轻松备份
傲梅轻松备份

傲梅轻松备份是一款专业易用的数据备份软件,为重要数据提供安全保障。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

Wise Folder Hider Pro
Wise Folder Hider Pro

Wise Folder Hider Pro 是一款专业级文件和文件夹隐藏加密软件,为私密数据添加多重保护。高频操作更强调就近处理,浏览、整理和跨目录移动文件时,来回切换和重复点击都会少很多。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

PinStack
PinStack

PinStack是一款轻量级的Windows平台剪贴板管理工具,优化您的剪贴板使用体验。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Seer
Seer

Seer是一款在Win平台下的空格键功能增强效率工具,只需轻敲空格键,就能预览几乎任何格式的文件。它更适合把零散的小功能集中起来使用,处理高频琐碎任务时会更省事。