以一致的方式重定向stdin和;使用optpasse将标准输出到python中的文件

以一致的方式重定向stdin和;使用optpasse将标准输出到python中的文件,python,stdout,stdin,optparse,Python,Stdout,Stdin,Optparse,我有十几个程序可以通过stdin或一个选项接受输入,我想以类似的方式为输出实现相同的功能 optpass代码如下所示: parser.add_option('-f', '--file', default='-', help='Specifies the input file. The default is stdin.') parser.add_option('-o', '--output', default='-', help='Spe

我有十几个程序可以通过stdin或一个选项接受输入,我想以类似的方式为输出实现相同的功能

optpass代码如下所示:

parser.add_option('-f', '--file',
       default='-',
       help='Specifies the input file.  The default is stdin.')
parser.add_option('-o', '--output',
       default='-',
       help='Specifies the output file.  The default is stdout.')
if opts.filename == '-':
    infile = sys.stdin
else:
    infile = open(opts.filename, "r")

if opts.output == '-':
    outfile = sys.stdout
else:
    outfile = open(opts.output, "w")
其余适用代码如下所示:

parser.add_option('-f', '--file',
       default='-',
       help='Specifies the input file.  The default is stdin.')
parser.add_option('-o', '--output',
       default='-',
       help='Specifies the output file.  The default is stdout.')
if opts.filename == '-':
    infile = sys.stdin
else:
    infile = open(opts.filename, "r")

if opts.output == '-':
    outfile = sys.stdout
else:
    outfile = open(opts.output, "w")

这段代码工作得很好,我喜欢它的简单性——但我还没有找到任何使用默认值“-”作为输出来指示标准输出的引用。这是一个很好的一致性解决方案,还是我忽略了更好或更令人期待的内容?

对于可以使用模块的输入文件。它遵循输入文件的常见约定:如果没有给定文件或文件名为“-”,它将读取stdin,否则它将从命令行给定的文件中读取

-f
--file
选项中没有必要。如果您的程序总是需要输入文件,那么它不是一个选项

-o
--output
用于指定

光轴 argparse 模块允许您将文件显式指定为参数:

#!/usr/bin/env python
import fileinput
import sys
from argparse import ArgumentParser

parser = ArgumentParser()
parser.add_argument('files', nargs='*', help='specify input files')
group = parser.add_mutually_exclusive_group()
group.add_argument('-o', '--output', 
    help='specify the output file.  The default is stdout')
group.add_argument('-i', '--inplace', action='store_true',
    help='modify files inplace')
args = parser.parse_args()

if args.output and args.output != '-':
   sys.stdout = open(args.output, 'w')

for line in fileinput.input(args.files, inplace=args.inplace):
    process(line)
注意:我在第二个示例中添加了
--inplace
选项:

$ python util-argparse.py --help
usage: util-argparse.py [-h] [-o OUTPUT | -i] [files [files ...]]

positional arguments:
  files                 specify input files

optional arguments:
  -h, --help            show this help message and exit
  -o OUTPUT, --output OUTPUT
                        specify the output file. The default is stdout
  -i, --inplace         modify files inplace
如果您可以使用(即Python 2.7+),它内置了对所需内容的支持:直接从

FileType
工厂创建可以传递给
ArgumentParser.add_argument()
的类型参数的对象。将
文件类型
对象作为其类型的参数将打开命令行参数[…]
文件类型
对象了解伪参数“-”,并自动将其转换为可读
文件类型
对象的sys.stdin和可写
文件类型
对象的sys.stdout

所以我的建议是简单地使用

import sys
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('file', type=argparse.FileType('r'),
    help="Specifies the input file")
parser.add_argument('output', type=argparse.FileType('w'),
    help="Specifies the output file")
args = parser.parse_args(sys.argv[1:])

# Here you can use your files
text = args.file.read()
args.output.write(text)
# … and so on
那你就可以了

> python spam.py file output 
文件
读取并输出到
输出
,或

> echo "Ni!" | python spam.py - output  
读取
“Ni!”
并输出到
输出,或

> python spam.py file -

这很好,因为对相关流使用
-
。如果要指出它,请将其添加到
帮助
字符串中

  parser.add_argument('file', type=argparse.FileType('r'),
    help="Specifies the input file, '-' for standard input")
为供参考,将显示使用信息

> python spam.py -h
usage: [-h] file output

positional arguments:
  file        Specifies the input file, '-' for standard input
  output      Specifies the output file, '-' for standard output

optional arguments:
  -h, --help  show this help message and exit

小澄清-我以前看到过一些帖子,其中建议在optpass/argparse中使用破折号作为指示符,程序应该从stdin读取。但我已经很久没看到了。我不知道这是什么背景-听起来熟悉吗?有什么见解吗?另外,Adam Wagner的建议看起来更简单易读。fileinput和csv模块对我来说不兼容,所以我不会在这些程序中使用fileinput。我这个假设错了吗?@KenFar:你说的“兼容”是什么意思
csv.reader(fileinput.input())
工作正常。哎呀,我搞错了。看起来是最好的解决方案,因为它还可以接受多个输入文件。谢谢。@J.F.Sebastian,您好,我注意到在argpase示例中,当输出为文件时,代码没有显式调用close(),这样可以吗?是的,您希望在脚本结束之前保持stdout打开。