Python argparse 与 stdin 互斥是选项之一

leo*_*hel 1 python json stdin argparse python-3.x

我希望我的脚本能够接收这些互斥的输入选项:

  • 包含 JSON ( ) 的输入文件script.py -i input.json
  • 包含 JSON ( ) 的字符串script.py '{"a":1}'
  • echo '{"a":1}' | script.py来自 stdin(或)的 JSON cat input.json | script.py

以及这些互斥的输出选项

  • 包含 JSON 的输出文件;
  • 标准输出中的 JSON。

所以我尝试使用这段代码

import json,sys,argparse
parser = argparse.ArgumentParser(description='Template for python script managing JSON as input/output format')

group = parser.add_mutually_exclusive_group()
group.add_argument('--input-file', '-i',  type=str, help='Input file name containing a valid JSON.', default=sys.stdin)
group.add_argument('json',    nargs='?',  type=str, help='Input string containing a valid JSON.' , default=sys.stdin)
parser.add_argument('--output-file', '-o',type=str, help='Output file name.')

args = parser.parse_args()

if not sys.stdin.isatty():
    data = sys.stdin.read()
else:
#    args = parser.parse_args()
    if args.input_file :
        data=open(args.input_file).read()
    elif args.json :
        data=args.json


datain=json.loads(data)

dataout=json.dumps(datain, indent=2)

if args.output_file :
        output_file=open(args.output_file, 'w')
        output_file.write(dataout+'\n')
        output_file.close()
else:
    print (dataout)
Run Code Online (Sandbox Code Playgroud)

但它不适用于标准输入,因为它至少需要两个group选项之一。

如何在输入选项列表中添加标准输入?

default=sys.stdin如果我这样称呼它,添加参数就可以了

echo '{}' | ./script.py -
Run Code Online (Sandbox Code Playgroud)

但不是那样的:

echo '{}' | ./script.py
Run Code Online (Sandbox Code Playgroud)

Rob*_*obᵩ 5

我会利用argparse.FileType默认值sys.stdin.

import json,sys,argparse
parser = argparse.ArgumentParser(description='Template for python script managing JSON as input/output format')

group = parser.add_mutually_exclusive_group()
group.add_argument(
    '--input-file', '-i',
    type=argparse.FileType('r'),
    default=sys.stdin,
    help='Input file name containing a valid JSON.')
group.add_argument(
    'json',
    nargs='?',
    type=str,
    help='Input string containing a valid JSON.')
parser.add_argument(
    '--output-file', '-o',
    type=argparse.FileType('w'),
    help='Output file name.',
    default=sys.stdout)

args = parser.parse_args()
data = args.json or args.input_file.read()

datain=json.loads(data)
dataout=json.dumps(datain, indent=2)
args.output_file.write(dataout)
Run Code Online (Sandbox Code Playgroud)

  • 是的,它正在等待下一行文本。毕竟,您的数据可能比一行长。输入完数据后,通过按操作系统使用的文件结束按键序列来指示文件结束。如果您使用的是 UNIX 或 Linux,则可能是 Control-D。如果您使用的是 Windows,则可能是 Control-Z。 (2认同)