argparsemain parser和sub-parsers
Posted 不吃饭就会放大招
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了argparsemain parser和sub-parsers相关的知识,希望对你有一定的参考价值。
在 Python 的 argparse
模块中,可以创建一个主解析器/父解析器(main parser)和多个子解析器(sub-parsers)。其中,main parser 中定义作用于整个项目的解析器,sub-parsers 中定义特定于某一些功能的子解析器。其中:
- main parser 中的选项称作
global option
,这些全局选项作用于整个项目 - sub-parsers 中的选项称作
sub option
,子选项的作用范围限制在子解析器内
通过使用一个主解析器和多个子解析器,能够创建更加灵活的命令行接口。
使用示例
下面的示例代码中,定义了一个主解析器 parser 和两个子解析器 parser_a 和 parser_b。
import argparse
# Set up the main parser
parser = argparse.ArgumentParser(description='A program with sub-commands') # 1
parser.add_argument('--verbose', action='store_true', help='increase output verbosity') # 2
# Set up subparsers for the different sub-commands
subparsers = parser.add_subparsers(title='sub-commands', dest='subcommand', description='valid subcommands', help='additional help') # 3
# Add subparsers for each sub-command
parser_a = subparsers.add_parser('command_a', help='description of command_a') # 4
parser_a.add_argument('--option_a', type=int, help='description of option_a') # 5
parser_b = subparsers.add_parser('command_b', help='description of command_b') # 6
parser_b.add_argument('--option_b', type=float, help='description of option_b') # 7
# Add subparsers for additional sub-commands here
# Parse the command-line arguments
args = parser.parse_args() # 8
if args.verbose:
print('Verbose mode enabled')
# Check which sub-command was specified and handle its options
if args.subcommand == 'command_a': # 9
if args.option_a:
print(f'command_a was run with option_a=args.option_a')
else:
print('command_a was run')
elif args.subcommand == 'command_b':
if args.option_b:
print(f'command_b was run with option_b=args.option_b')
else:
print('command_b was run')
- 在
1
处,通过argparse.ArgumentParser()
定义主解析器 parser - 在
2
处,通过.add_argument()
方法为主解析器添加一个全局选项:–verbose - 在
3
处,通过.add_subparsers()
方法创建子解析器 subparsers,作为主解析器 parser 的子解析器,每个 subparser 都通过不同的子命令行指示(参数dest
) - 在
4
和6
处,通过subparsers.add_parser()
创建了两个子解析器 parser_a 和 parser_b - 在
5
和7
处,通过add_argument()
为子解析器分别添加子选项 –option_a 和 –option_b - 在
8
处,使用parser.parse_args()
对命令行参数进行解析 - 在
9
处,args.subcommand
即3
处的参数dest
,通过子解析器的名称进行判断
命令行执行程序:
$ python my_tool.py command_a --option_a 42
args.subcommand
指定了当前使用哪个子解析器,上面的例子中,command_a 指定子解析器为 parser_a,同时指定了解析器 parser_a 的选项 –option_a。输出:
command_a was run with option_a=42
在命令行同时使用 –verbose 和 –option_a:
$ python my_tool.py --verbose command_a --option_a 42
此时程序开启 verbose 模式,同时执行子解析器 parser_a,输出:
Verbose mode enabled
command_a was run with option_a=42
使用“import dateutil”和“dateutil.parser.parse()”时出现AttributeError,但使用“from dateutil import parser”时没有问题
【中文标题】使用“import dateutil”和“dateutil.parser.parse()”时出现AttributeError,但使用“from dateutil import parser”时没有问题【英文标题】:AttributeError when using "import dateutil" and "dateutil.parser.parse()" but no problems when using "from dateutil import parser" 【发布时间】:2014-06-16 14:12:03 【问题描述】:我在 Python 2.7.3 中使用 dateutil
module。我只是想使用:
import dateutil
dateutil.parser.parse("01-02-2013")
但是我得到了一个错误:
AttributeError: 'module' object has no attribute 'parser'
我检查了dateutil
有哪些属性:
print dir(dateutil)
# output: ['__author__', '__builtins__', '__doc__', '__file__', '__license__',
# '__name__', '__package__', '__path__', '__version__']
问题是,当我尝试直接从dateutil
导入parser
时,它似乎确实存在:
from dateutil import parser
print parser.parse("01-02-2013")
# output: 2013-01-02 00:00:00
在from dateutil import parser
之后,parser
也神奇地出现在了导入的dateutil
本身中:
print dir(dateutil)
# output: ['__author__', '__builtins__', '__doc__', '__file__', '__license__',
# '__name__', '__package__', '__path__', '__version__', 'parser',
# 'relativedelta', 'tz']
请注意,此列表中仍然缺少一些其他属性(例如 rrule
)。
有人知道怎么回事吗?
【问题讨论】:
【参考方案1】:您尚未导入dateutil.parser
。您可以看到它,但您必须以某种方式导入它。
>>> import dateutil.parser
>>> dateutil.parser.parse("01-02-2013")
datetime.datetime(2013, 1, 2, 0, 0)
这是因为parser.py
是dateutil
包中的一个模块。它是文件夹结构中的一个单独文件。
回答你在 cmets 中提出的问题,relativedelta
和 tz
在你 from dateutil import parser
之后出现在命名空间中的原因是因为 parser
本身导入了 relativedelta
和 tz
。
如果你查看dateutil/parser.py
的源代码,你可以看到导入。
# -*- coding:iso-8859-1 -*-
"""
Copyright (c) 2003-2007 Gustavo Niemeyer <gustavo@niemeyer.net>
This module offers extensions to the standard Python
datetime module.
"""
... snip ...
from . import relativedelta
from . import tz
【讨论】:
我认为您可以像导入任何其他模块一样导入它。例如,如果我想使用datetime.date.today()
,我会先使用import datetime
,然后再使用print datetime.date.today()
。这对dateutil
不起作用有什么原因吗?
我明白了。那么dateutil
中的所有其他属性(如rrule
)都是单独的文件,因此您总是必须使用import dateutil.[attribute_name]
来使用它们?
不一样,date
是datetime.py
文件中的一个类,而dateutil.parser
实际上是一个单独的文件,parser.py
在dateutil包中。
@Neftas 是的,差不多就是这样。
谢谢!关于为什么在from dateutil import parser
之后,第二个print dir(dateutil)
突然显示relativedelta
和tz
有什么想法吗?以上是关于argparsemain parser和sub-parsers的主要内容,如果未能解决你的问题,请参考以下文章
XML Pull Parser 和 SAX Parser 有啥区别
使用“import dateutil”和“dateutil.parser.parse()”时出现AttributeError,但使用“from dateutil import parser”时没有问题
dateutil.parser.parse() 和丢失的时区信息