Вывод трубы из командной строки в сценарий python

Я хочу запустить команду mysql и установить вывод этой переменной в мой скрипт python.

Вот команда оболочки, которую я пытаюсь запустить:

$ mysql my_database --html -e "select * from limbs" | ./script.py

Вот скрипт python:

#!/usr/bin/env python

import sys

def hello(variable):
    print variable

Как я могу принять переменную в скрипте python и распечатать ее?

Ответ 1

Вам нужно прочитать stdin для извлечения данных в скрипте python, например

#!/usr/bin/env python

import sys

def hello(variable):
    print variable

data = sys.stdin.read()
hello(data)

Если все, что вы хотите сделать, это захватить некоторые данные из базы данных mysql, а затем манипулировать им с помощью Python, я бы пропустил его в сценарий и просто использовал модуль MySql Python для выполнения SQL-запроса.

Ответ 2

Если вы хотите, чтобы ваш скрипт вел себя как много инструментов командной строки unix и принимал трубку или имя файла в качестве первого аргумента, вы можете использовать следующее:

#!/usr/bin/env python
import sys

# use stdin if it full                                                        
if not sys.stdin.isatty():
    input_stream = sys.stdin

# otherwise, read the given filename                                            
else:
    try:
        input_filename = sys.argv[1]
    except IndexError:
        message = 'need filename as first argument if stdin is not full'
        raise IndexError(message)
    else:
        input_stream = open(input_filename, 'rU')

for line in input_stream:
    print line # do something useful with each line

Ответ 3

Когда вы подаете вывод одной команды в скрипт pytho, она переходит к sys.stdin. Вы можете читать sys.stdin так же, как файл. Пример:

import sys

print sys.stdin.read()

Эта программа буквально выводит свой вклад.

Ответ 4

Поскольку этот ответ появляется в Google наверху при поиске piping data to a python script, я хотел бы добавить еще один метод, который я нашел в Поварской книге J. Beazley Python после поиска менее "серьезного" подхода, чем использование sys. IMO, более pythonic и понятным даже для новых пользователей.

import fileinput
with fileinput.input() as f_input:
    for line in f_input:
        print(line, end='')

Этот подход также работает для команд, структурированных следующим образом:

$ ls | ./filein.py          # Prints a directory listing to stdout.
$ ./filein.py /etc/passwd   # Reads /etc/passwd to stdout.
$ ./filein.py < /etc/passwd # Reads /etc/passwd to stdout.

Если вам требуются более сложные решения, вы можете сопоставить argparse и fileinput как показано в этом вопросе, с помощью martinth:

import argpase
import fileinput

if __name__ == '__main__':
    parser = ArgumentParser()
    parser.add_argument('--dummy', help='dummy argument')
    parser.add_argument('files', metavar='FILE', nargs='*', help='files to read, if empty, stdin is used')
    args = parser.parse_args()

    # If you would call fileinput.input() without files it would try to process all arguments.
    # We pass '-' as only file when argparse got no files which will cause fileinput to read from stdin
    for line in fileinput.input(files=args.files if len(args.files) > 0 else ('-', )):
        print(line)

"""

Ответ 5

Это старый вопрос, но если вы на bash, и ваш скрипт имеет что-то вроде

import sys
x = sys.argv[1]
print x

и вы хотите передать вывод из команды, выполненной в оболочке, в sys.argv [], вы можете сделать это с помощью

test.py $(some_command -w arguments)

Если вы ожидаете одну строку от вашего вывода, она будет передана обратно как argv [1]. Если вы ожидаете нескольких строк, они будут передаваться по отдельности и помещаться в массив argv [], и если вы хотите проверить содержимое, которое вы сделали бы

print sys.argv[1:] #starting at index 1 so you don't get the script name in the output

Если это тип вывода, который будет возвращен как массив, вам придется изменить свой скрипт python, чтобы получить весь вывод, помещенный в один вызываемый объект. Есть способы, упомянутые выше, но вы также можете просто вызвать команду непосредственно в своем скрипте и сохранить вывод в переменной с помощью

import subprocess
x = subprocess.check_output('mysql my_database --html -e "select * from limbs"',shell=True)
print x

которые выходят

whatever_output
came_from_the
command_execution
in_the_same_format

* операторы печати произвольны и просто выбраны для отображения значений

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