处理argparse转义字符作为选项

时间:2015-12-08 00:02:57

标签: python delimiter argparse

argparse库处理转义字符(比如\ t到tab和\ n到换行符)的方式与我不同。 An answer to this question提供了一个解决方案,但我想让用户看不到它。

鉴于该计划:

#!/usr/bin/env python3
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-d', '--delimiter', default='\t')
args = parser.parse_args()
print(args)

您将收到此输出:

bash$ parser.py -d \t
Namespace(delimiter='t')

bash$ parser.py -d \\t
Namespace(delimiter='\\t')

bash$ parser.py -d '\t'
Namespace(delimiter='\\t')

bash$ parser.py -d '\\t'
Namespace(delimiter='\\\\t')

bash$ parser.py -d "\t"
Namespace(delimiter='\\t')

bash$ parser.py -d "\\t"
Namespace(delimiter='\\t')

bash$ parser.py -d $'\t'
Namespace(delimiter='\t')

bash$ parser.py -d $'\\t'
Namespace(delimiter='\\t')

bash$ parser.py -d $"\t"
Namespace(delimiter='$\\t')

bash$ parser.py -d $"\\t"
Namespace(delimiter='$\\t')

我只能用

获得所需的参数
parser.py -d $'\t'

但我希望输入看起来像

parser.py -d \t 

或更不优选

parser.py -d '\t'
parser.py -d "\t"

如果我想改变行为,我可以使用argparse库做些什么吗? 如果没有,我是否可以在现有的argparse库之上编写行为? 如果不是,这只是bash将参数传递给argparse的方式,因此不在我手中吗? 如果这是真的,这通常会记录给用户,还是假设这种行为是正常的?

4 个答案:

答案 0 :(得分:3)

您在namespace中看到的字符串正是sys.argv中显示的字符串 - 由bash和解释程序创建的字符串。 parser不会处理或调整此字符串。它只是设置namespace中的值。您可以在解析之前通过print sys.argv验证这一点。

如果您明白用户想要什么,那么我建议在解析后修改args.delimiter。解析器的主要目的是弄清楚用户想要什么。作为程序员,您可以以任何方式插入和应用该信息。

一旦您完成了一个令人满意的解析后功能,您就可以将其作为type实现此参数(就像int()float()对数字字符串所做的那样)。但要关注后解析处理。

答案 1 :(得分:3)

假设问题部分是关于如何执行@hpaulj解释的后处理,并且因为我在上面的链接中看不到Python 3的直接解决方案,这是一个快速的解决方案:

import codecs

def unescaped_str(arg_str):
    return codecs.decode(str(arg_str), 'unicode_escape')

然后在解析器中:

parser.add_argument('-d', '--delimiter', type=unescaped_str, default='\t')

这将使您不太理想的案例起作用:

parser.py -d '\t'
parser.py -d "\t"

但不是所谓的未转义\t。无论如何,这种解决方案可能很危险,因为没有检查机制......

答案 2 :(得分:1)

就我个人而言,我只是期望这种行为 - 你的shell解释了一些项目并传递了一个文字制表符,或者反斜杠和一个字母-t-并且不一定希望Python程序能够进行第二级解释(并且没有任何内容)在argparse做它。)

尽管如此,Python已经为此建立了解释器;见this question and answers

答案 3 :(得分:1)

这是正确处理带引号('\t'"\t")输入用例的快速方法(尽管它仅专门处理您特定的制表符用例输入):

parser.add_argument('-d', '--delimiter', type=lambda d: '\t' if d == '\\t' else d)

首先注意以下几点:在Python中,"\t"是制表符,转义的"\\t"是两个字符的字符串(第一个字符是"\",第二个是"t")。您可以使用len("\t"), len("\\t")(提供1, 2)进行检查。

当用户在命令行上用引号引起来的-d '\t'时,python将收到字符串'\t'(实际上是两个字符,“反斜杠”和“ t”)。我们要用一个“制表符”替换该两个字符的字符串。 type参数采用函数作为预处理参数的方式。 lambda函数检查两个字符的字符串,并将其替换为制表符。