Чтение из файла или стандартного ввода
Я написал утилиту командной строки, которая использует getopt для разбора аргументов, заданных в командной строке. Я также хотел бы, чтобы имя файла было необязательным аргументом, например, в других утилитах, таких как grep, cut и т. д. Итак, я хотел бы, чтобы он имел следующее использование
tool -d character -f integer [filename]
Как я могу реализовать следующее?
- если задано имя файла, чтение из файла.
- если имя файла не задано, считайте из STDIN.
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; в противном случае он читает из каждого файла по очереди, аналогично Perlwhile(<>).
мне нравится общая идиома использования контекстного менеджера, но (тоже) тривиальное решение заканчивается закрытием
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