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的方式,因此不在我手中吗? 如果这是真的,这通常会记录给用户,还是假设这种行为是正常的?
答案 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函数检查两个字符的字符串,并将其替换为制表符。