【问题标题】:Python: Parse multiple datatypes using argparsePython:使用 argparse 解析多种数据类型
【发布时间】:2013-06-11 04:59:55
【问题描述】:

我尝试使用 argparse 来了解它是如何解析给定列表的:

parser = argparse.ArgumentParser()

parser.add_argument('--ls', nargs='*', type=str, default = [])
Out[92]: _StoreAction(option_strings=['--ls'], dest='ls', nargs='*', const=None, default=[], type=<type 'str'>, choices=None, help=None, metavar=None)

args = parser.parse_args("--ls 'tomato' 'jug' 'andes'".split())

args
Out[94]: Namespace(ls=["'tomato'", "'jug'", "'andes'"])

args.ls
Out[96]: ["'tomato'", "'jug'", "'ande'"]

args.ls[0]
Out[97]: "'tomato'"

eval(args.ls[0])
Out[98]: 'tomato'

Q1:上述方法可行,但有没有更好的方法来访问列表中的值?

然后我尝试用字典来解析给定的字典:

dict_parser = argparse.ArgumentParser()
dict_parser.add_argument('--dict', nargs='*',type=dict,default={})

Out[104]: _StoreAction(option_strings=['--dict'], dest='dict', nargs='*', const=None, default={}, type=<type 'dict'>, choices=None, help=None, metavar=None)

arg2 = dict_parser.parse_args("--dict {'name':'man', 'address': 'kac', 'tags':'don'}")
usage: -c [-h] [--dict [DICT [DICT ...]]]
-c: error: unrecognized arguments: - - d i c t   { ' n a m e ' : ' m a n' ,   ' a d d r e s s ' :   ' k a c' ,   ' t a g s ' : ' d o n ' }
To exit: use 'exit', 'quit', or Ctrl-D.
An exception has occurred, use %tb to see the full traceback.

SystemExit: 2

那是行不通的。 Q2:以上对字典有什么作用?

Q3:现在我想要

python my.py --ls tomato jug andes  --dict {'name':'man', 'address': 'kac', 'tags':'don'}

待解析

我该怎么做?

我提到了http://parezcoydigo.wordpress.com/2012/08/04/from-argparse-to-dictionary-in-python-2-7/

...并发现在字典下分配所有内容非常有用。有人可以简化此任务以解析参数中的多种数据类型吗?

【问题讨论】:

  • Q1:你想要什么?你得到的参数正是你提出的,包括引号。如果您不想这样,请不要用引号将参数括起来。
  • Q2:你把 Python 和 shell 搞混了。参数通常在 shell 上给出,并且不包含任何 Python 字典的概念。因此,您不能通过参数创建 Python 字典,事实上,您甚至不应该尝试。只需将每个键设为单独的选项并照此使用即可。
  • @Evert 你的意思是“--ls 番茄壶安第斯山脉”??
  • 请注意,这在我看来是一种非常规的使用选项的方式。 python my.py --ls tomato jug andes --name man --address kac --tags don 怎么了?

标签: python python-2.7 argparse


【解决方案1】:
import ast
dict_parser.add_argument('--dict', nargs='*',type=ast.literal_eval,default={})
args = dict_parser.parse_args(["--dict", "{'name':'man', 'address': 'kac', 'tags':'don'}"])

【讨论】:

  • 这将评估您作为参数传递的任何内容,因此使用风险自负
【解决方案2】:

parser.add_argument('--ls', nargs='*', type=str, default = []) Q1:上述方法可行,但有没有更好的方法来访问列表中的值?

我经常认为“越简单越好”,这是一种非常简单的做事方式,我想说没有更好的方法。但是,还有其他方法。

dict_parser.add_argument('--dict', nargs='*',type=dict,default={}) arg2 = dict_parser.parse_args("--dict {'name':'man', 'address': 'kac', 'tags':'don'}") Q2:以上对字典有什么作用?

我建议你使用 json 解析你的字符串:

>>> class FromJSON():
...     def __init__(self, string):
...         self.string = string
...     def decode(self):
...         return json.loads(self.string)
...    
>>> dict_parser.add_argument('--dict',type=FromJSON)
>>> arg2 = dict_parser.parse_args(['--dict', '{"name":"man", "address": "kac", "tags":"don"}'])

虽然 JSON 很像 python,但它不是 python。它对引号(值仅由 双引号 包围)和尾随逗号(没有)很挑剔。但至少它对代码注入是安全的!当然你应该用引号括起你的参数

您可能有另一个解决方案来将 dict 作为参数,那就是去掉括号:

>>> parser.add_argument('--dict', nargs='*', type=str, default = [])
>>> args = parser.parse_args(['--dict', 'name:man', 'address:kac', 'tags:don'])
>>> args.dict = dict([arg.split(':') for arg in args.dict])
>>> print args.dict
{'tags': 'don', 'name': 'man', 'address': 'kac'}

Q3:现在我想要

python my.py --ls tomato jug andes  --dict {'name':'man', 'address': 'kac', 'tags':'don'}

待解析

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--dict', type=FromJSON, default=FromJSON("{}"))
>>> parser.add_argument('--ls', nargs='*', type=str, default = [])
>>> args = parser.parse_args(['--ls', 'tomato', 'jug', 'andes', '--dict', '{"name":"man", "address": "kac", "tags":"don"}'])
>>> args.ls
['tomato', 'jug', 'andes']
>>> args.dict
<__main__.FromJSON instance at 0x7f932dd20c20>
>>> args.dict.decode()
{u'tags': u'don', u'name': u'man', u'address': u'kac'}

关于FromJSON(),可以改进一下是这样的:

class JsonToDict():
    def __call__(self, string):
        return json.loads(string)

您可以按如下方式使用:

dict_parser.add_argument('--dict',type=JsonToDict())

HTH

【讨论】:

  • 这是 python 令人惊奇的一面。是的,我也会研究 json。对我有用。谢谢
  • 所以我应该使用 JsonToDict 而不是 3 种 Json 方法?
  • 嘿,args = parser.parse_args(['--ls', 'tomato', 'jug', 'andes', '--dict', '{"name":"man" , "地址": "kac", "标签":"don"}']) ;使用这个 eval(''.join(args.dict)) 也可以。只是说不要为它写额外的类
  • eval() 与用户输入一起使用就像在不带避孕套的情况下与陌生人打交道! 永远不要eval() 与用户输入的代码一起使用,您可能会遇到严重的安全问题。总有另一种更好的方法来完成几乎没有安全漏洞的工作。在python中eval()可能有很好的用途,但我还没有看到。
猜你喜欢
  • 2018-12-14
  • 1970-01-01
  • 2014-03-04
  • 1970-01-01
  • 2015-03-04
  • 2013-11-06
  • 1970-01-01
  • 1970-01-01
  • 2016-05-30
相关资源
最近更新 更多