Как использовать подпроцесс в Python - PullRequest
0 голосов
/ 05 апреля 2020

Я хотел бы выполнить следующую команду оболочки в python: grep 'string' file | tail -1 | cut -c 1-3

Я пытался:

import subprocess

i = 1
while i < 1070:
    file = "sorted." + str(i) + ".txt"
    string = "2x"
    subprocess.call(grep 'string' file | tail -1 | cut -c 1-3)
    i = i + 1

Любая помощь будет оценена. Спасибо.

Ответы [ 3 ]

1 голос
/ 05 апреля 2020

Прежде всего, все, что вы передаете в subprocess.call, должно быть строкой. Имена grep, file, tail и cut не определены в вашем коде, и вам нужно превратить все выражение в строку. Поскольку строка поиска для команды grep должна быть динамической c, вам необходимо создать последнюю строку перед передачей ее в качестве аргумента в функцию.

import subprocess

i = 1
while i < 1070:
    file = "sorted." + str(i) + ".txt"
    string = "2x"
    command_string = 'grep {0} {1} | tail -1 | cut -c 1-3'.format(string, file)
    subprocess.call(command_string)
    i = i + 1

Возможно, вы захотите передать дополнительный аргумент subprocess.call: shell=True. Аргумент обеспечит выполнение команды через оболочку.

Ваша команда использует cut. Возможно, вы захотите получить выходные данные подпроцесса, поэтому лучшим вариантом будет создание нового объекта процесса и использование subprocess.communicate с полученным выходным захватом:

import subprocess

i = 1
while i < 1070:
    file = "sorted." + str(i) + ".txt"
    string = "2x"
    command_string = 'grep {0} {1} | tail -1 | cut -c 1-3'.format(string, file)

    p = subprocess.Popen(command_string, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdoutdata, stderrdata = p.communicate()

    # stdoutdata now contains the output of the shell commands and you can use it
    # in your program

    i = i + 1

РЕДАКТИРОВАТЬ: Вот информация о как сохранить данные в текстовом файле, как это требуется в комментарии.

import subprocess

outputs = []

i = 1
while i < 1070:
    file = "sorted." + str(i) + ".txt"
    string = "2x"
    command_string = 'grep {0} {1} | tail -1 | cut -c 1-3'.format(string, file)

    p = subprocess.Popen(command_string, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    stdoutdata, stderrdata = p.communicate()

    # stdoutdata now contains the output of the shell commands and you can use it
    # in your program, like writing the output to a file.

    outputs.append(stdoutdata)

    i = i + 1


with open('output.txt', 'w') as f:
    f.write('\n'.join(outputs))
0 голосов
/ 05 апреля 2020

Ваша команда должна быть представлена ​​в виде строки. Кроме того, если вы хотите получить выходные данные своей команды, вы можете использовать следующее:

subprocess.run("grep 'string' file | tail -1 | cut -c 1-3", shell=True, capture_output=True, check=True)

, где capture_output (работает в Python3 .7 +) возвращает объект с returncode, stdout и stderr, а флаг check вызовет исключение в случае сбоя вашей команды.

0 голосов
/ 05 апреля 2020

Подпроцесс ожидает аргументы в виде строки или массива:

subprocess.call("grep '{}' {} | tail -1 | cut -c 1-3".format(string, file), shell=True)

shell=True является nececairy, потому что вы используете команды c, определяемые оболочкой, как конвейер.

Однако, в этом случае может быть намного проще реализовать всю программу в чистом виде python.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...