当前位置:

首页 > 编程开发 > 如何使用 Python 内置库创建一个命令行应用程序?

如何使用 Python 内置库创建一个命令行应用程序?

当创建一个应用程序时,通常希望能够告诉你的应用程序如何做某事。有两种流行的方法来完成这项任务,你可以让应用程序接受命令行参数,或者创建一个图形化的用户接口。有些应用程序两者都支持。当你需要在服务器上运行你的代码时,命令行接口很有帮助。大多数服务器没有图形化界面,特别当它们是Linux服务器时。在这种情况下,即使你想运行图形用户界面,你也可能无法运行。Python有一个叫做argparse的内置库,可以用它来创建一个命令行界面。在这篇文章中,你将了解到以下内容。解析实参创建有用的信息添加别名使用相互排

本文目录

    如何使用 Python 内置库创建一个命令行应用程序?

    当创建一个应用程序时,通常希望能够告诉你的应用程序如何做某事。有两种流行的方法来完成这项任务,你可以让应用程序接受命令行参数,或者创建一个图形化的用户接口。有些应用程序两者都支持。

    当你需要在服务器上运行你的代码时,命令行接口很有帮助。大多数服务器没有图形化界面,特别当它们是Linux服务器时。在这种情况下,即使你想运行图形用户界面,你也可能无法运行。

    Python 有一个叫做 argparse 的内置库,可以用它来创建一个命令行界面。在这篇文章中,你将了解到以下内容。

    • 解析实参
    • 创建有用的信息
    • 添加别名
    • 使用相互排斥的参数
    • 创建一个简单的搜索工具

    argparse模块的内容比本文要介绍的多得多。如果你想知道更多关于它的信息,你可以查看文档。

    现在是时候开始从命令行中解析参数了。

    解析参数

    在学习如何使用 argparse 之前,最好知道还有一种方法可以向 Python 脚本传递参数。你可以向 Python 脚本传递任何参数,并通过使用 sys 模块访问这些参数。

    为了了解它是如何工作的,创建一个名为 sys_args.py 的文件,并在其中输入以下代码:

    # sys_args.py
     import sys
     def main():
     print('You passed the following arguments:')
     print(sys.argv)
     if __name__ == '__main__':
     main()

    这段代码导入sys并打印出sys.argv中的任何内容。argv属性包含了所有传递给脚本的东西的列表,其中第一项是脚本本身。

    下面是一个例子,说明当你运行这段代码和几个参数的时候会发生什么。

    $ python3 sys_args.py --s 45
     You passed the following arguments:
     ['sys_args.py', '--s', '45']

    使用sys.argv的问题是,你无法控制可以传递给你的应用程序的参数。

    • 不能忽略参数
    • 不能创建默认参数
    • 无法判断什么是有效参数

    这就是为什么使用 argparse 是使用 Python 标准库的方法。argparse 模块是非常强大和有用的。让我们想一想,一个命令行应用程序所遵循的常见过程。

    • pass:传入一个文件
    • do:在你的程序中对该文件做一些处理
    • output :输出结果

    下面是一个关于如何工作的通用例子。继续创建file_parser.py并添加以下代码。

    # file_parser.py
     import argparse
     def file_parser(input_file, output_file=''):
     print(f'Processing {input_file}')
     print('Finished processing')
     if output_file:
     print(f'Creating {output_file}')
     def main():
     parser = argparse.ArgumentParser('File parser')
     parser.add_argument('--infile', help='Input file')
     parser.add_argument('--out', help='Output file')
     args = parser.parse_args()
     if args.infile:
     file_parser(args.infile, args.out)
     if __name__ == '__main__':
     main()

    file_parser()函数是进行解析的逻辑所在。在这个例子中,它只接收一个文件名,并将其打印出来。output_file参数的默认值是一个空字符串。

    程序的重点在 main()中。在这里你创建了一个 argparse.ArgumentParser()的实例,并给你的解析器起了一个名字。然后你添加两个参数, --infile和 --out。为了使用这个解析器,你需要调用 parse_args(),它将返回传递给你的程序的任何有效参数。最后,你要检查用户是否使用了 --infile 标志。如果他们使用了,那么你就运行 file_parser()。

    下面是你如何在你的终端中运行代码。

    $ python file_parser.py --infile something.txt
     Processing something.txt
     Finished processing

    在这里,你用 --infile标志和一个文件名来运行你的脚本。这将运行 main(),然后调用 file_parser()。

    下一步是使用你在代码中声明的两个命令行参数尝试运行你的应用程序。

    $ python file_parser.py --infile something.txt --out output.txt
     Processing something.txt
     Finished processing
     Creating output.txt

    这一次,你得到了一个额外的输出行,提到了输出文件名。这代表你的代码逻辑中的一个分支。当你指定一个输出文件时,你可以让你的代码通过使用一个新的代码块或一个函数来生成该文件。如果你不指定一个输出文件,那么那个代码块就不会运行。

    当你使用argparse创建你的命令行工具时,你可以很容易地添加信息,当你的用户不确定如何正确地与你的程序互动时,可以帮助他们。

    现在是时候找出如何从你的应用程序中获得帮助了

    创建帮助信息

    argparse库将使用你在创建每个参数时提供的信息,自动为你的应用程序创建一个有用的信息。这里是代码:

    # file_parser.py
     import argparse
     def file_parser(input_file, output_file=''):
     print(f'Processing {input_file}')
     print('Finished processing')
     if output_file:
     print(f'Creating {output_file}')
     def main():
     parser = argparse.ArgumentParser('File parser')
     parser.add_argument('--infile', help='Input file')
     parser.add_argument('--out', help='Output file')
     args = parser.parse_args()
     if args.infile:
     file_parser(args.infile, args.out)
     if __name__ == '__main__':
     main()

    现在试着用 -h标志运行这段代码,你应该看到以下内容。

    $ file_parser.py -h
     usage: File parser [-h] [--infile INFILE] [--out OUT]
     optional arguments:
     -h, --help show this help message and exit
     --infile INFILEInput file
     --out OUTOutput file

    add_argument()的帮助参数被用来创建上面的帮助信息。argparse会自动添加 -h和 -help选项。你可以通过给它一个描述和后记来使你的帮助信息更丰富。

    让我们用它们来改进你的帮助信息。首先,把上面的代码复制到一个新的文件中,命名为 file_parser_with_description.py,然后把它修改成下面的样子。

    # file_parser_with_description.py
     import argparse
     def file_parser(input_file, output_file=''):
     print(f'Processing {input_file}')
     print('Finished processing')
     if output_file:
     print(f'Creating {output_file}')
     def main():
     parser = argparse.ArgumentParser(
     'File parser',
     description='PyParse - The File Processor',
     epilog='Thank you for choosing PyParse!',
     )
     parser.add_argument('--infile', help='Input file for conversion')
     parser.add_argument('--out', help='Converted output file')
     args = parser.parse_args()
     if args.infile:
     file_parser(args.infile, args.out)
     if __name__ == '__main__':
     main()

    在这里,把description和epilog参数传递给ArgumentParser。还更新了 add_argument()的帮助参数,使其更具描述性。

    在做了这些修改之后,当你用 -h或 --help运行这个脚本时,你会看到以下输出。

    $ python file_parser_with_description.py -h
     usage: File parser [-h] [--infile INFILE] [--out OUT]
     PyParse - The File Processor
     optional arguments:
     -h, --help show this help message and exit
     --infile INFILEInput file for conversion
     --out OUTConverted output file
     Thank you for choosing PyParse!

    现在可以在你的帮助输出中看到新的description 和epilog。这给了你的命令行程序一些额外的修饰。

    你也可以通过ArgumentParser的 add_help参数在你的应用程序中完全禁用帮助。如果你认为你的帮助文本过于冗长,你可以像这样禁用它。

    # file_parser_no_help.py
     import argparse
     def file_parser(input_file, output_file=''):
     print(f'Processing {input_file}')
     print('Finished processing')
     if output_file:
     print(f'Creating {output_file}')
     def main():
     parser = argparse.ArgumentParser(
     'File parser',
     description='PyParse - The File Processor',
     epilog='Thank you for choosing PyParse!',
     add_help=False,
     )
     parser.add_argument('--infile', help='Input file for conversion')
     parser.add_argument('--out', help='Converted output file')
     args = parser.parse_args()
     if args.infile:
     file_parser(args.infile, args.out)
     if __name__ == '__main__':
     main()

    通过将 add_help设置为 False,你将禁用 -h和 --help标志。

    你可以看到下面的演示。

    $ python file_parser_no_help.py --help
     usage: File parser [--infile INFILE] [--out OUT]
     File parser: error: unrecognized arguments: --help

    在下一节中,你将学习如何为你的参数添加别名!

    添加别名

    别名是一个花哨的词,指的是使用一个替代的标志来做同样的事情。例如,你知道你可以使用 -h和 --help来访问程序的帮助信息。-h是 --help的别名,反之亦然。

    看看 main()里面的 parser.add_argument()方法有什么变化。

    # file_parser_aliases.py
     import argparse
     def file_parser(input_file, output_file=''):
     print(f'Processing {input_file}')
     print('Finished processing')
     if output_file:
     print(f'Creating {output_file}')
     def main():
     parser = argparse.ArgumentParser(
     'File parser',
     description='PyParse - The File Processor',
     epilog='Thank you for choosing PyParse!',
     add_help=False,
     )
     parser.add_argument('-i', '--infile', help='Input file for conversion')
     parser.add_argument('-o', '--out', help='Converted output file')
     args = parser.parse_args()
     if args.infile:
     file_parser(args.infile, args.out)
     if __name__ == '__main__':
     main()

    这里你改变了第一个 add_argument(),除了接受 -infile之外,还接受了 -i,你还在第二个 add_argument()中加入了 -o。这样就可以使用两个新的快捷标志来运行你的代码。

    下面是一个例子。

    $ python3 file_parser_aliases.py -i something.txt -o output.txt
     Processing something.txt
     Finished processing
     Creating output.txt

    如果你去看argparse文档,你会发现也可以给子解析器添加别名。子解析器是一种在你的应用程序中创建子命令的方法,这样它就可以做其他事情。一个很好的例子是Docker,一个虚拟化或容器应用程序。它有一系列的命令,你可以在docker下运行,以及docker compose等等。这些命令中的每一个都有独立的子命令,你都可以使用。

    下面是一个典型的docker命令,用于运行一个容器。

    docker exec -it container_name bash

    这将用docker启动一个容器。而如果你要使用docker compose,你将使用一组不同的命令。exec和compose是subparsers的例子。

    使用相互排斥的参数

    有时你需要让你的应用程序接受一些参数,但不接受其他参数。例如,你可能想限制你的应用程序,使它只能创建或删除文件,而不是同时创建和删除。

    argparse模块提供了 add_mutually_exclusive_group()方法,它就是这样做的。

    将你的两个参数添加到一个组对象中,使其相互排斥,如下面的例子。

    # file_parser_exclusive.py
     import argparse
     def file_parser(input_file, output_file=''):
     print(f'Processing {input_file}')
     print('Finished processing')
     if output_file:
     print(f'Creating {output_file}')
     def main():
     parser = argparse.ArgumentParser(
     'File parser',
     description='PyParse - The File Processor',
     epilog='Thank you for choosing PyParse!',
     add_help=False,
     )
     group = parser.add_mutually_exclusive_group()
     group.add_argument('-i', '--infile', help='Input file for conversion')
     group.add_argument('-o', '--out', help='Converted output file')
     args = parser.parse_args()
     if args.infile:
     file_parser(args.infile, args.out)
     if __name__ == '__main__':
     main()

    首先,你创建了一个相互排斥的组。然后,你把 -i和 -o参数添加到组中,而不是添加到解析器对象中。现在这两个参数是互斥的。

    下面是当你试图用这两个参数运行你的代码时发生的情况。

    $ python3 file_parser_exclusive.py -i something.txt -o output.txt
     usage: File parser [-i INFILE | -o OUT]
     File parser: error: argument -o/--out: not allowed with argument -i/--infile

    用这两个参数运行你的代码,会使你的解析器向用户显示一条错误信息,解释他们做错了什么。

    在涵盖了所有这些与使用argparse有关的信息之后,你已经准备好应用你的新技能来创建一个简单的搜索工具了

    创建一个简单的搜索工具

    在开始创建一个应用程序之前,弄清楚你要完成的任务总是好的。你在本节中想要建立的应用程序应该能够搜索特定文件类型的文件。为了使它更有趣,你可以添加一个额外的参数,让你也能选择性地搜索特定的文件大小。

    你可以使用 Python 的 glob 模块来搜索文件类型。你可以在这里阅读关于这个模块的所有信息。

    https://docs.python.org/3/library/glob.html

    还有一个 fnmatch 模块,glob 自己也使用它。你现在应该使用 glob,因为它更容易使用,但是如果你有兴趣写一些更专业的东西,那么 fnmatch 可能是你正在寻找的。

    然而,由于你希望能够通过文件大小来选择性地过滤返回的文件,你可以使用 pathlib,它包括一个类似 glob 的接口。glob 模块本身并不提供文件大小的信息。

    你可以先创建一个名为 pysearch.py 的文件并输入以下代码。

    # pysearch.py
     import argparse
     import pathlib
     def search_folder(path, extension, file_size=None):
     """
     Search folder for files
     """
     folder = pathlib.Path(path)
     files = list(folder.rglob(f'*.{extension}'))
     if not files:
     print(f'No files found with {extension=}')
     return
     if file_size is not None:
     files = [
     f
     for f in files
     if f.stat().st_size >= file_size
     ]
     print(f'{len(files)} *.{extension} files found:')
     for file_path in files:
     print(file_path)

     在上面的代码片段中,首先导入了argparse和pathlib。接下来,创建了search_folder()函数,它接收了三个参数。

    • path - 要搜索的文件夹
    • extension - 要寻找的文件扩展名
    • file_size - 要过滤的文件大小,以字节为单位。

    把路径变成pathlib.Path对象,然后使用其rglob()方法在文件夹中搜索用户传入的扩展名。如果没有找到文件,就向用户打印一个有意义的信息,然后退出。

    如果找到了任何文件,就检查是否已经设置了filesize。如果它被设置了,就用一个list comprehension来过滤出小于指定的filesize的文件。

    接下来,打印出找到的文件的数量,最后在这些文件上循环,打印出它们的名字。

    为了使这一切正常工作,需要创建一个命令行界面。你可以通过添加一个包含argparse代码的main()函数来做到这一点,像这样。

    def main():
     parser = argparse.ArgumentParser(
     'PySearch',
     description='PySearch - The Python Powered File Searcher',
     )
     parser.add_argument('-p', '--path',
     help='The path to search for files',
     required=True,
     dest='path')
     parser.add_argument('-e', '--ext',
     help='The extension to search for',
     required=True,
     dest='extension')
     parser.add_argument('-s', '--size',
     help='The file size to filter on in bytes',
     type=int,
     dest='size',
     default=None)
     args = parser.parse_args()
     search_folder(args.path, args.extension, args.size)
     if __name__ == '__main__':
     main()

    这个ArgumentParser()有三个参数,与你传递给search_folder()的参数相对应。让--path和--ext参数成为必需的,而让--size参数成为可选的。注意,--size参数被设置为type=int,这意味着你不能把它传成字符串。

    add_argument()函数有一个新的参数。它是dest参数,可以用它来告诉你的参数分析器在哪里保存传递给它们的参数。

    下面是一个脚本运行的例子。

    $ python3 pysearch.py -p /Users/michael/Dropbox/python101code/chapter32_argparse -e py -s 650
     6 *.py files found:
     /Users/michael/Dropbox/python101code/chapter32_argparse/file_parser_aliases2.py
     /Users/michael/Dropbox/python101code/chapter32_argparse/pysearch.py
     /Users/michael/Dropbox/python101code/chapter32_argparse/file_parser_aliases.py
     /Users/michael/Dropbox/python101code/chapter32_argparse/file_parser_with_description.py
     /Users/michael/Dropbox/python101code/chapter32_argparse/file_parser_exclusive.py
     /Users/michael/Dropbox/python101code/chapter32_argparse/file_parser_no_help.py

     现在试试用-s和一个字符串来运行它。

    $ python3 pysearch.py -p /Users/michael/Dropbox/python101code/chapter32_argparse -e py -s python
     usage: PySearch [-h] -p PATH -e EXTENSION [-s SIZE]
     PySearch: error: argument -s/--size: invalid int value: 'python'

    这次我们收到了一个错误,因为-s和-size只接受整数。在你自己的机器上运行一下这段代码,看看当你使用-s和整数时,它是否按你想要的方式工作。

    这里有一些想法,你可以用来改进你的代码版本。

       更好地处理扩展文件。现在,它将接受 *.py,这不会像你期望的那样工作。

       更新代码,以便你可以一次搜索多个扩展名

       更新代码,以便对文件大小的范围进行过滤(例如,1MB-5MB)。

    还有很多其他的功能和改进,你可以添加到这个代码中,比如添加错误处理或单元测试。

    总结

    argparse模块功能齐全,可以用来创建庞大、灵活的命令行应用程序。在本章中,你了解了以下内容。

    • 解析参数
    • 创建有用的信息
    • 添加别名
    • 使用相互排斥的参数
    • 创建一个简单的搜索工具

    你可以用argparse模块做更多的事情,不完全包括本章所讲的。请务必查看文档以了解全部细节。现在去试试吧。你会发现,一旦你掌握了使用argparse的窍门,你就可以创建一些非常整洁的应用程序了。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 命令行 Python
    相关文章 更多
    python删除一个列表里的重复元素的方法与代码示例
    python删除一个列表里的重复元素的方法与代码示例

    学习如何使用Python高效删除列表中的重复元素。本文提供5种常见方法的代码示例,涵盖保持顺序与不保持顺序的场景,适合初学者和进阶开发者参考。

    Python写接口的步骤及完整代码示例
    Python写接口的步骤及完整代码示例

    详细讲解使用Python编写Web接口的核心步骤与完整代码示例,涵盖环境准备、路由定义、数据校验、服务启动及调试测试方法。

    codex怎么读取word文档及docx文件操作教程
    codex怎么读取word文档及docx文件操作教程

    介绍如何利用编程工具读取和解析Word文档(docx格式),涵盖基础文本提取代码示例、结构化数据处理逻辑,以及处理复杂排版时的技术局限与替代方案。

    怎么在Python中调用C语言代码提升性能
    怎么在Python中调用C语言代码提升性能

    详细讲解在Python中调用C语言代码提升性能的完整实践指南,包含原理分析、编译步骤、ctypes与CFFI具体实现、性能对比及常见陷阱。

    Python与C语言的性能差异及底层原理
    Python与C语言的性能差异及底层原理

    深入解析Python与C语言在执行效率上的数量级差异,从编译机制、变量内存布局、动态类型推断到GIL锁,系统阐明底层核心原理。

    Python和C语言哪个更适合编程入门
    Python和C语言哪个更适合编程入门

    客观对比Python与C语言在心智负担、底层机制与学习反馈上的核心差异,提供清晰有据的选择标准与切实的入门学习路径。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    langgraph python guide中文入门教程详解
    langgraph python guide中文入门教程详解

    本篇LangGraph Python中文入门教程详解,系统梳理StateGraph状态机定义、节点编写、边与条件路由、检查点持久化(MemorySaver)等核心机制,提供从环境安装到完整循环智能体构建的代码示例与实操指导。

    Windows 安装 Python:从官方入口到虚拟环境的可复现实践
    Windows 安装 Python:从官方入口到虚拟环境的可复现实践

    面向后端开发者,基于 Python 官方文档说明如何在 Windows 上安装 Python、创建 venv 虚拟环境及使用 pip 管理依赖。包含可复制命令、验证方法及工具选择边界,避免常见配置误区。

    查看更多
    精品专题 更多
    装机必备
    装机必备

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

    Windows
    Windows

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

    PDF教程
    PDF教程

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

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。