Согласованный способ перенаправления stdin & stdout в файлы на python с помощью optparse
у меня есть дюжина программ, которые могут принимать ввод через stdin или опцию, и я хотел бы реализовать те же функции аналогичным образом для вывода.
код optparse выглядит следующим образом:
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")
этот код отлично работает, и мне нравится его простота, но я не смог найти ссылку на кого - либо, использующего значение по умолчанию " - " для вывода, чтобы указать stdout. Это хорошо последовательное решение или я упускаю что-то лучшее или более ожидаемое?
2 ответов
для входных файлов вы можете использовать fileinput модуль. Он следует общему соглашению для входных файлов: если нет файлов или имени файла" -", он читает stdin, иначе он читает из файлов, заданных в командной строке.
нет необходимости в -f и --file параметры. Если ваша программа всегда требует входного файла, то это не вариант.
-o и --output используется для указания имя выходного файла в различных программы.
optparse
#!/usr/bin/env python
import fileinput
import sys
from optparse import OptionParser
parser = OptionParser()
parser.add_option('-o', '--output',
    help='Specifies the output file.  The default is stdout.')
options, files = parser.parse_args()
if options.output and options.output != '-':
   sys.stdout = open(options.output, 'w')
for line in fileinput.input(files):
    process(line)
argparse
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)
Примечание: я добавил во втором примере:
$ 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
если вы можете использовать argparse (т. е. Python 2.7+), он имеет встроенную поддержку того, что вы хотите: прямо из argparse doc
на
FileTypeфабрика создает объекты, которые могут быть переданы аргументу типаArgumentParser.add_argument(). Аргументы, которые имеютFileTypeобъекты в качестве их типа откроют аргументы командной строки [ ... ]FileTypeобъекты понимают псевдо-аргумент ' - ' и автоматически преобразуют его в sys.stdin-стандартный поток ввода для чтенияFileTypeобъекты иsys.stdoutдля перезаписываемыхFileTypeобъекты.
поэтому мой совет-просто использовать
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 
читать file и вывода output или 
> echo "Ni!" | python spam.py - output  
читать "Ni!" и вывода output или
> python spam.py file -
...
и это хорошо, так как использование - для соответствующего потока  это соглашение, которое используют многие программы. Если хочешь ...  укажите это, добавьте его в help строки.
  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
