Я имею скрипт 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 + Dstdin
всегда True
в булевом контексте.Я хотел бы портативный способ сделать это, если это возможно.
Обрабатывайте аргументы, не являющиеся именами файлов, как хотите, поэтому вы получаете массив аргументов без параметров, а затем передаете этот массив в качестве параметра в fileinput.input ():
import fileinput
for line in fileinput.input(remaining_args):
process(line)
Для 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
Нет надежного способа определить, подключен ли sys.stdin
к чему-либо, и это делать нецелесообразно (например, пользователь хочет вставить данные). Обнаружить наличие имени файла в качестве аргумента и использовать stdin, если ничего не найдено.
Argparse позволяет сделать это довольно простым способом, и вы действительно должны использовать его вместо optparse
, если у вас нет проблем с совместимостью.
Код будет выглядеть примерно так:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--input', type = argparse.FileType('r'), default = '-')
Теперь у вас есть парсер, который будет разбирать аргументы командной строки, использовать файл, если он его видит, или использовать стандартный ввод, если его нет.