将元组作为命令行参数传递

43

我的要求是将元组作为命令行参数传递,就像这样:

--data (1,2,3,4)

我尝试使用argparse模块,但如果我像这样传递参数,它会将其接收为字符串'(1,2,3,4)'。我尝试在argparse.add_argument中给出type=tuple,但这里没有用。

我需要添加一个新的类型类并将其传递给add_argument的类型参数吗?

更新

根据答案,我尝试了ast.literal_eval。谢谢。但结果中会有空格,如下所示。

(1,2,3,4)
<type 'str'>
(1, 2, 3, 4)
<type 'tuple'>

1
根据重复内容,“ast.literal_eval”将是一个适当的“type”参数。 - jonrsharpe
根据 argparse 文档,type 必须是一个函数(callable),它接受一个简单的字符串并将其转换为所需的对象。tuple('(1,2)') 接受一个字符串,但会将其拆分为字符,例如 ('(', '1', ',', '2', ')')。此外要注意用户可能会输入 --data (1, 2, 3,4)。Shell 会按空格进行拆分。 - hpaulj
5
重复的链接与解析类似于“(1, 2)”这样的字符串有关,但不涉及argparse问题的一面。 - hpaulj
https://dev59.com/_2sz5IYBdhLWcg3w17fQ#18003926 建议使用 json.loads 来解析看起来像字典和列表(但不是元组)的字符串。 - hpaulj
为什么不将参数存储为字符串并将其传递给eval()以将其转换为元组。 - muman
3个回答

63

data参数的nargs设置为nargs="+"(表示一个或多个),类型设置为int,然后您可以在命令行上像这样设置参数:

--data 1 2 3 4

args.data现在将是一个列表,其中包含[1, 2, 3, 4]

如果你一定要使用元组,可以这样做:

my_tuple = tuple(args.data)

将所有内容综合起来:

parser = argparse.ArgumentParser()
parser.add_argument('--data', nargs='+', type=int)
args = parser.parse_args()
my_tuple = tuple(args.data)

3
对不起,这不是我的要求。请再看一遍我的问题。我知道这种方法。 - user1423015
7
那您改变一下要求吧 ;) 用户不需要按特定方式格式化其参数。但使用多个参数是正常的。 - Alastair McCormack
2
Alastair,你是正确的。最终我改变了我的需求 :-). - user1423015
最棒的是,在我的情况下,你可以使用nargs="+"或nargs=<int>与action="append"结合来指定列表的列表,从而允许在参数列表中多次出现--data。太好了! - resi
@AlastairMcCormack,你怎么设置这样的默认值? - KansaiRobot

6
如果您想扩展这个功能,不想处理语法树,并在参数中提供元组转换,您需要一个自定义的argparse类型。(我需要这个是因为我的解析器在一个包中,我不想要求我的用户都编写my_tuple = tuple(args.data)。通过使用一个参数类型,您还可以接收带有括号的字符串,就像原始问题一样。此外,我不会包括nargs,因为它会将您的自定义类型输出包装成一个列表,这基本上违背了您自定义类型的目的。我映射了一个浮点数,因为我的输入格式类似于"0.9, 0.99",但是您的整数也可以工作:
def tuple_type(strings):
    strings = strings.replace("(", "").replace(")", "")
    mapped_int = map(int, strings.split(","))
    return tuple(mapped_int)

parser = argparse.ArgumentParser()
parser.add_argument('--data', type=tuple_type)
args = parser.parse_args()

这样您可以发送 --data "(1,2,3,4)" 或者 --data "1,2,3,4"


2

我有同样的需求。在标准包中找不到,所以自己写了一个。使用Python 3x编写,并放在简单的argv解析器中,每次调用一个参数:

  • var 默认传递正确类型。
  • argval 找到命令行字符串。逗号分隔,没有空格。例如:1,2,3或one,two,three。

适用于bash shell,可能需要引号、其他调整来适应其他shell和操作系统。相同的技术也适用于非列表类型。此版本基于var[0]创建一个同类列表或元组。

示例:

./foo.py   --mytuple 1,2,3,4,5

代码:

def chk_arg( var, argstr, dbg=False): 
    ### loop on sys.argv here .....
    # if list/tuple type, use list comprehension
    # converts csv list to list or tuple 'type(var)' of 'type(var[0])' items. 
    if type(var) is list or type(var) is tuple:  
        val = type(var)([type(var[0])(i) for i in argval.split(',')]) 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接