Чтение из файла или стандартного ввода



Я написал утилиту командной строки, которая использует getopt для разбора аргументов, заданных в командной строке. Я также хотел бы, чтобы имя файла было необязательным аргументом, например, в других утилитах, таких как grep, cut и т. д. Итак, я хотел бы, чтобы он имел следующее использование



tool -d character -f integer [filename]


Как я могу реализовать следующее?




  • если задано имя файла, чтение из файла.

  • если имя файла не задано, считайте из STDIN.

669   7  

7 ответов:

в самых простых выражениях:

import sys
# parse command line
if file_name_given:
    inf = open(file_name_given)
else:
    inf = sys.stdin

в этот момент Вы бы использовали inf для чтения из файла. В зависимости от того, было дано имя, это было чтение из файла или с клавиатуры.

когда вам нужно закрыть файл, вы можете сделать это:

if inf is not sys.stdin:
    inf.close()

однако, в большинстве случаев это будет безвредно, чтобы закрыть sys.stdin Если вы закончили с этим.

The fileinput модуль может делать то, что вы хотите, при условии, что аргументами в args затем:

import fileinput
for line in fileinput.input(args):
    print line

если args пуст, то fileinput.input() будет читать из stdin; в противном случае он читает из каждого файла по очереди, аналогично Perl while(<>).

мне нравится общая идиома использования контекстного менеджера, но (тоже) тривиальное решение заканчивается закрытием sys.stdin когда вы выходите из with заявление, которого я хочу избежать.

заимствование из ответ, вот решение:

import sys
import contextlib

@contextlib.contextmanager
def _smart_open(filename, mode='Ur'):
    if filename == '-':
        if mode is None or mode == '' or 'r' in mode:
            fh = sys.stdin
        else:
            fh = sys.stdout
    else:
        fh = open(filename, mode)
    try:
        yield fh
    finally:
        if filename is not '-':
            fh.close()

if __name__ == '__main__':
    args = sys.argv[1:]
    if args == []:
        args = ['-']
    for filearg in args:
        with _smart_open(filearg) as handle:
            do_stuff(handle)

Я полагаю, вы могли бы достичь что-то похожее с os.dup() но код, который я приготовил для этого, оказался более сложным и более волшебным, тогда как вышеизложенное несколько неуклюже, но очень просто.

чтобы использовать питона with заявление, можно использовать следующий код:

import sys
with open(sys.argv[1], 'r') if len(sys.argv) > 1 else sys.stdin as f:
    # read data using f
    # ......

Я предпочитаю использовать " - " в качестве индикатора, который вы должны прочитать из stdin, это более явно:

import sys
with open(sys.argv[1], 'r') if sys.argv[1] is not "-" else sys.stdin as f:
    pass # do something here

не прямой ответ, но связанный.

обычно при написании скрипта python вы можете использовать argparse пакета. В этом случае вы можете использовать:

parser = argparse.ArgumentParser()
parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin)

'?'. Один аргумент будет использоваться из командной строки, если это возможно, и изготавливается как один элемент. Если аргумент командной строки отсутствует, будет создано значение по умолчанию.

и здесь мы устанавливаем по умолчанию sys.stdin;

Так что если есть файл, он будет прочитайте его, и если нет, он будет принимать входные данные от stdin "примечание: что мы используем позиционный аргумент в примере выше"

для большего посещения:https://docs.python.org/2/library/argparse.html#nargs

что-то типа:

if input_from_file:
    f = open(file_name, "rt")
else:
    f = sys.stdin
inL = f.readline()
while inL:
    print inL.rstrip()
    inL = f.readline()

Comments

    Ничего не найдено.