在互斥参数组中使用标准输入

Using stdin in a mutually exclusive argument group

我正在尝试在脚本中使用 argparse,这样我就可以将字符串作为参数或通过标准输入进行传递。我想我可以为此使用 add_mutually_exclusive_group,并设置 required=True 来强制只需要一个参数。因此,我创建了以下脚本 (my_script.py):

#!/usr/bin/env python

import argparse
from sys import stdin

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('str_arg', nargs='?', type=str)
group.add_argument('str_in', nargs='?', type=argparse.FileType('r'), default=stdin)
args = parser.parse_args()
print args.str_arg or args.str_in.readline()

将字符串作为参数传递可以正常工作。但是,当我尝试像这样从标准输入中传输字符串时:

$ echo Hello | python my_script.py

Python 抱怨 one of the arguments str_arg str_in is required。我究竟做错了什么?有没有更好的方法来实现这一点?

您似乎不应该尝试使用花哨的 argparse 功能来执行此操作,只是一些简单的逻辑:

import argparse
from sys import stdin

parser = argparse.ArgumentParser()
parser.add_argument('str_arg', nargs='?', type=str)
args = parser.parse_args()
print(args.str_arg or stdin.readline())

在 shell 中,您可以使用反引号而不是管道将 echo Whatever 的输出作为参数传递:

$ python my_script.py `echo whatever`

互斥组中的 2 个位置不起作用。

import argparse

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('str_arg', nargs='?')
group.add_argument('str_in', nargs='?')
args = parser.parse_args()
print(args)

样本运行:

0217:~/mypy$ python3 stack49705916.py 
usage: stack49705916.py [-h] (str_arg | str_in)
stack49705916.py: error: one of the arguments str_arg str_in is required

0904:~/mypy$ python3 stack49705916.py foo
Namespace(str_arg='foo', str_in=None)

0904:~/mypy$ python3 stack49705916.py foo bar
usage: stack49705916.py [-h] (str_arg | str_in)
stack49705916.py: error: argument str_in: not allowed with argument str_arg

管道不能替代命令行参数。 stdin需单独阅读

import argparse, sys
print(sys.argv)
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('str_arg', nargs='?')
group.add_argument('str_in', nargs='?')
args = parser.parse_args()
print(args)
print(sys.stdin.read())

0909:~/mypy$ echo 'hello' | python3 stack49705916.py foo
['stack49705916.py', 'foo']
Namespace(str_arg='foo', str_in=None)
hello

argparse.FileType('r')- 识别为 stdin

print(sys.argv)
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--str_in', type=argparse.FileType('r'))
args = parser.parse_args()
print(args)
print(args.str_in.read())

运行

0945:~/mypy$ python3 stack49705916.py -i test.txt
['stack49705916.py', '-i', 'test.txt']
Namespace(str_in=<_io.TextIOWrapper name='test.txt' mode='r' encoding='UTF-8'>)
2000+0
2001+2
2002+1

0946:~/mypy$ python3 stack49705916.py -i -
['stack49705916.py', '-i', '-']
Namespace(str_in=<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>)
typing hello on input line

typing hello on input line


0947:~/mypy$ echo Hello | python3 stack49705916.py -i -
['stack49705916.py', '-i', '-']
Namespace(str_in=<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>)
Hello

0947:~/mypy$