Как читать из stdin или из файла, если никакие данные не передаются по каналу в Python?

Я имею скрипт CLI и хочу, чтобы он считал данные из файла. Это должно смочь считать его двумя способами:

  • cat data.txt | ./my_script.py
  • ./my_script.py data.txt

— немного как grep, например.

Что я знаю:

  • sys.argv и optparse позвольте мне считать любой args и опции легко.
  • sys.stdin позвольте мне считать данные, переданные по каналу в
  • fileinput сделайте полный процесс автоматическим

К сожалению:

  • использование fileinput использование stdin и любой args, как введено. Таким образом, я не могу использовать опции, которые не являются именами файлов, поскольку это пытается открыть их.
  • sys.stdin.readlines() хорошо работает, но если я не передаю данных по каналу, они зависают, пока я не ввожу Ctrl + D
  • Я не знаю, как реализовать, "если ничто в stdin, читайте из файла в args" потому что stdin всегда True в булевом контексте.

Я хотел бы портативный способ сделать это, если это возможно.

17
задан jez 26 January 2015 в 14:03
поделиться

4 ответа

Обрабатывайте аргументы, не являющиеся именами файлов, как хотите, поэтому вы получаете массив аргументов без параметров, а затем передаете этот массив в качестве параметра в fileinput.input ():

import fileinput
for line in fileinput.input(remaining_args):
    process(line)
10
ответ дан 30 November 2019 в 10:49
поделиться

Для unix / linux вы можете определить, передаются ли данные по конвейеру, посмотрев на os.isatty (0)

$ date | python -c "import os;print os.isatty(0)"
False
$ python -c "import os;print os.isatty(0)"
True

Я не конечно есть эквивалент для Windows.

edit Хорошо, я пробовал это с python2.6 в Windows XP

C:\Python26>echo "hello" | python.exe -c "import os;print os.isatty(0)"  
False

C:\Python26> python.exe -c "import os;print os.isatty(0)"  
True

Так что, возможно, это не все безнадежно для Windows

9
ответ дан 30 November 2019 в 10:49
поделиться

Нет надежного способа определить, подключен ли sys.stdin к чему-либо, и это делать нецелесообразно (например, пользователь хочет вставить данные). Обнаружить наличие имени файла в качестве аргумента и использовать stdin, если ничего не найдено.

3
ответ дан 30 November 2019 в 10:49
поделиться

Argparse позволяет сделать это довольно простым способом, и вы действительно должны использовать его вместо optparse, если у вас нет проблем с совместимостью.

Код будет выглядеть примерно так:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--input', type = argparse.FileType('r'), default = '-')

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

20
ответ дан 30 November 2019 в 10:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: