Несколько аргументов с stdin в Python

у меня есть жгучий вопрос, который касается передачи нескольких аргументов stdin при запуске скрипта Python из терминала Unix. Рассмотрим следующую команду:

$ cat file.txt | python3.1 pythonfile.py

содержимое file.txt (доступ через команду "cat") будет передан скрипту python в качестве стандартного ввода. Что работает (хотя более элегантный способ был бы неплохо). Но теперь я должен передать еще один аргумент, который является просто словом, которое будет использоваться как запрос (и позже двух словах). Но я не могу узнать, как это сделать правильно, так как кошачья труба даст ошибки. И вы не можете использовать стандартный input() в Python, потому что это приведет к ошибке EOF (вы не можете объединить stdin и input() в Python).

4 ответов


хотя ответ Стива Барнса будет работать, это не самый "питонический" способ делать вещи. Более элегантный способ-использовать аргументы sys и открывать и читать файл в самом скрипте. Таким образом, вам не нужно передавать выходные данные файла и находить обходной путь, вы можете просто передать имя файла в качестве другого параметра.

что-то вроде (в скрипте python):

import sys

with open(sys.argv[1].strip) as f:
    file_contents = f.readlines()
    # Do basic transformations on file contents here
    transformed_file_contents = format(file_contents)

# Do the rest of your actions outside the with block, 
# this will allow the file to close and is the idiomatic 
# way to do this in python

Так (в командной строке):

python3.1 pythonfile.py file.txt postarg1 postarg2

Я достаточно уверен, что маркер stdin с do the trick:

cat file.txt | python3.1 prearg - postarg

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


на argparse модуль даст вам много больше гибкости, чтобы играть с аргументами командной строки.

import argparse

parser = argparse.ArgumentParser(prog='uppercase')
parser.add_argument('-f','--filename',
                    help='Any text file will do.')                # filename arg
parser.add_argument('-u','--uppercase', action='store_true',
                    help='If set, all letters become uppercase.') # boolean arg
args = parser.parse_args()
if args.filename:                       # if a filename is supplied...
    print 'reading file...'
    f = open(args.filename).read()
    if args.uppercase:                  # and if boolean argument is given...
        print f.upper()                 # do your thing
    else:
        print f                         # or do nothing

else:
    parser.print_help()                 # or print help

поэтому, когда вы бежите без аргументов, вы получаете:

/home/myuser$ python test.py
usage: uppercase [-h] [-f FILENAME] [-u]

optional arguments:
  -h, --help            show this help message and exit
  -f FILENAME, --filename FILENAME
                        Any text file will do.
  -u, --uppercase       If set, all letters become uppercase.

предположим, что существует абсолютная необходимость в передаче содержимого как stdin, а не filepath, потому что ваш скрипт находится в контейнере docker или что-то еще, но у вас также есть другие аргументы, которые вы должны передать...так что сделайте что-то вроде этого

import sys
import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-dothis', '--DoThis', help='True or False', required=True)
    # add as many such arguments as u want

    args = vars(parser.parse_args())

    if args['DoThis']=="True":
        content = ""
        for line in sys.stdin:
            content = content + line
        print "stdin - " + content

чтобы запустить этот скрипт do

$ cat abc.txt | script.py -это правда!--2-->

$ echo "hello" | script.py -это правда!--2-->

содержимое переменной будет храниться в нем все, что было напечатано на левой стороне канала,"|", и вы также сможете предоставить аргументы сценария.