Home  >  Article  >  Backend Development  >  Create a command line application using Python built-in libraries

Create a command line application using Python built-in libraries

PHPz
PHPzforward
2023-04-16 22:31:01869browse

Create a command line application using Python built-in libraries

When creating an application, you usually want to be able to tell your application how to do something. There are two popular ways to accomplish this task, you can have the application accept command line arguments, or you can create a graphical user interface. Some apps support both.

The command line interface is helpful when you need to run your code on the server. Most servers do not have a graphical interface, especially if they are Linux servers. In this case, even if you want to run the GUI, you may not be able to.

Python has a built-in library called argparse that can be used to create a command line interface. In this article, you will learn the following.

  • Parse arguments
  • Create useful information
  • Add aliases
  • Use mutually exclusive parameters
  • Create a simple There is much more to the search tool

argparse module than can be covered in this article. If you want to know more about it, you can check out the documentation.

Now it's time to start parsing the parameters from the command line.

Parsing Arguments

Before learning how to use argparse, it’s good to know that there is another way to pass parameters to a Python script. You can pass any parameters to a Python script and access these parameters by using the sys module.

To understand how it works, create a file called sys_args.py and enter the following code in it:

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

This code imports sys and prints out sys.argv of any content. The argv attribute contains a list of everything passed to the script, with the first item being the script itself.

Here is an example of what happens when you run this code with a few parameters.

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

The problem with using sys.argv is that you have no control over the arguments that can be passed to your application.

  • Cannot ignore parameters
  • Cannot create default parameters
  • Cannot determine what are valid parameters

This is why using argparse is to use Python standard library methods. The argparse module is very powerful and useful. Let's think about the common process followed by a command line application.

  • pass: Pass in a file
  • do: Do ​​some processing on the file in your program
  • output: Output the result

Below is a generic example of how this works. Go ahead and create file_parser.py and add the following code.

# 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()

The file_parser() function is the logic for parsing. In this example, it just receives a filename and prints it. The default value of the output_file parameter is an empty string.

The focus of the program is in main(). Here you create an instance of argparse.ArgumentParser() and give your parser a name. Then you add two parameters, --infile and --out. In order to use this parser, you need to call parse_args(), which will return any valid arguments passed to your program. Finally, you want to check whether the user used the --infile flag. If they do, then you run file_parser().

Here's how you run the code in your terminal.

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

Here, you run your script with the --infile flag and a filename. This will run main() and then call file_parser().

The next step is to try running your application using the two command line arguments you declared in your code.

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

This time, you get an extra output line mentioning the output file name. This represents a branch in your code's logic. When you specify an output file, you can have your code generate the file by using a new code block or a function. If you don't specify an output file, that block of code won't run.

When you use argparse to create your command line tools, you can easily add information that can help your users when they are unsure of how to properly interact with your program.

Now it's time to find out how to get help from your application

Create help information

The argparse library will use the information you provide when creating each argument , automatically creates a useful message for your application. Here is the code:

# 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()

Now try running this code with the -h flag and you should see the following.

$ 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

The help parameter of add_argument() is used to create the above help message. argparse automatically adds the -h and -help options. You can make your help informative by giving it a description and a postscript.

Let us use them to improve your help messages. First, copy the above code into a new file, name it file_parser_with_description.py, and then modify it to look like below.

# 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()

Here, pass the description and epilog parameters to ArgumentParser. Also updated the help argument for add_argument() to be more descriptive.

After making these changes, when you run this script with -h or --help, you will see the following output.

$ 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的窍门,你就可以创建一些非常整洁的应用程序了。

The above is the detailed content of Create a command line application using Python built-in libraries. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:51cto.com. If there is any infringement, please contact admin@php.cn delete