Arhn - архитектура программирования

Модуль подпроцесса Python, как мне ввести первую из серий конвейерных команд?

Я пытаюсь использовать модуль подпроцесса Python. Что мне нужно, так это послать входные данные первому процессу, чьи выходные данные станут входными данными второго процесса. Ситуация в основном почти такая же, как пример, приведенный в документации здесь: http://docs.python.org/library/subprocess.html#replacing-shell-pipeline за исключением того, что мне нужно ввести первую команду. Вот этот пример скопирован:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]

Если мы изменим первую строку на:

p1 = Popen(["cat"], stdout=PIPE, stdin=PIPE)

Как предоставить входную строку процессу? Если я попытаюсь это сделать, изменив последнюю строку на:

output = p2.communicate(input=inputstring)[0]

Это не работает.

У меня есть рабочая версия, которая просто сохраняет вывод первой команды в строку, а затем передает ее второй команде. Это не страшно, так как параллелизм, который можно было бы использовать, по сути, отсутствует (в моем реальном случае использования первая команда завершится довольно быстро и выдаст весь свой вывод в конце). Вот рабочая версия полностью:

import subprocess

simple = """Writing some text
with some lines in which the
word line occurs but others
where it does
not
"""

def run ():
  catcommand = [ "cat" ]
  catprocess = subprocess.Popen(catcommand,
                                stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
  (catout, caterr) = catprocess.communicate(input=simple)
  grepcommand = [ "grep", "line" ]
  grepprocess = subprocess.Popen(grepcommand,
                                stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
  (grepout, greperr) = grepprocess.communicate(input=catout)
  print "--- output ----"
  print grepout 
  print "--- error ----"
  print greperr 

if __name__ == "__main__":
  run()

Я надеюсь, что я был достаточно ясен, спасибо за любую помощь.

22.02.2011

Ответы:


1

Если вы сделаете

from subprocess import Popen, PIPE
p1 = Popen(["cat"], stdout=PIPE, stdin=PIPE)

Вы должны сделать p1.communicate("Your Input to the p1"), и это будет проходить через ТРУБУ. Стандартный ввод — это вход процесса, и вы должны общаться только с ним.

Программа, которую дали, абсолютно нормальная, с этим проблем вроде нет.

22.02.2011
  • Привет, спасибо за ответ, я думаю, что я просто оставлю программу как есть. Я подумал, что может быть неэффективно использовать строку для хранения результата первого процесса. 22.02.2011
  • Нет, не совсем. Вполне нормально хранить вывод в виде строки. 22.02.2011

  • 2

    Я предполагаю, что cat, grep — это просто примеры команд, иначе вы могли бы использовать чистое решение Python без подпроцессов, например:

    for line in simple.splitlines():
        if "line" in line:
           print(line)
    

    Или, если вы хотите использовать grep:

    from subprocess import Popen, PIPE
    
    output = Popen(['grep', 'line'], stdin=PIPE, stdout=PIPE).communicate(simple)[0]
    print output,
    

    Вы можете передать вывод первой команды второй, не сохраняя его сначала в строке:

    from subprocess import Popen, PIPE
    from threading import Thread
    
    # start commands in parallel
    first = Popen(first_command, stdin=PIPE, stdout=PIPE)
    second = Popen(second_command, stdin=first.stdout, stdout=PIPE)
    first.stdout.close() # notify `first` if `second` exits 
    first.stdout = None # avoid I/O on it in `.communicate()`
    
    # feed input to the first command
    Thread(target=first.communicate, args=[simple]).start() # avoid blocking
    
    # get output from the second command at the same time
    output = second.communicate()[0]
    print output,
    

    Если вы не хотите хранить весь ввод/вывод в памяти; вам могут понадобиться потоки (для чтения/записи фрагментами без блокировки) или цикл выбора (работает на POSIX).

    Если есть несколько команд, может быть более читаемым просто использовать оболочку напрямую, как это предлагается @Troels Folke, или использовать < href="https://stackoverflow.com/a/16709666/4279">библиотека, такая как plumbum, которая скрывает все кровавые детали ручной эмуляции оболочки.

    20.08.2013

    3

    Хм, почему бы не добавить немного (ba)sh? :-)

    from subprocess import Popen, PIPE
    cproc = Popen('cat | grep line', stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True)
    out, err = cproc.communicate("this line has the word line in it")
    

    ОСТЕРЕГАЙТЕСЬ, хотя:

    • Это работает только в системах, которые используют оболочку, совместимую с Bourne Shell (как и большинство *nix'ов).

    • Usign shell=True и размещение пользовательского ввода в командной строке - плохая идея, если вы сначала не экранируете пользовательский ввод. Подробнее читайте в документации подпроцесса -> «Часто используемые аргументы».

    • Это уродливо, не переносимо, не питонично и так далее...

    РЕДАКТИРОВАТЬ: нет необходимости использовать cat, если все, что вы хотите сделать, это grep. Просто передайте входные данные напрямую в grep или, что еще лучше, используйте регулярные выражения Python.

    20.08.2013
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..