>  기사  >  백엔드 개발  >  Python 내장 라이브러리를 사용하여 명령줄 애플리케이션 만들기

Python 내장 라이브러리를 사용하여 명령줄 애플리케이션 만들기

PHPz
PHPz앞으로
2023-04-16 22:31:01869검색

Python 내장 라이브러리를 사용하여 명령줄 애플리케이션 만들기

애플리케이션을 만들 때 일반적으로 애플리케이션에 작업 방법을 알려줄 수 있기를 원합니다. 이 작업을 수행하는 두 가지 일반적인 방법이 있습니다. 응용 프로그램이 명령줄 인수를 허용하도록 하거나 그래픽 사용자 인터페이스를 만드는 것입니다. 일부 앱은 두 가지를 모두 지원합니다.

명령줄 인터페이스는 서버에서 코드를 실행해야 할 때 유용합니다. 대부분의 서버에는 그래픽 인터페이스가 없습니다. 특히 Linux 서버인 경우 더욱 그렇습니다. 이 경우 GUI를 실행하고 싶어도 실행하지 못할 수도 있습니다.

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 사용의 문제점은 애플리케이션에 전달할 수 있는 인수를 제어할 수 없다는 것입니다.

  • 매개변수를 무시할 수 없습니다.
  • 기본 매개변수를 생성할 수 없습니다.
  • 유효한 매개변수가 무엇인지 알 수 없습니다.

이것이 Python 표준 라이브러리를 사용하는 방법인 argparse를 사용하는 이유입니다. 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()

여기서 설명과 에필로그 매개변수를 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的窍门,你就可以创建一些非常整洁的应用程序了。

위 내용은 Python 내장 라이브러리를 사용하여 명령줄 애플리케이션 만들기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 51cto.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제