Подтвердить что ты не робот

Передача команд оболочки двойной кавычки в python на subprocess.Popen()?

Я пытаюсь передать команду, которая работает в оболочке, которая работает только с буквальными двойными кавычками в командной строке вокруг аргумента "concat:file1|file2" для ffmpeg.

Я не могу выполнить эту работу с python с помощью subprocess.Popen(). У кого-нибудь есть идея, как передать кавычки в подпроцесс .Popen?

Вот код:

command = "ffmpeg -i "concat:1.ts|2.ts" -vcodec copy -acodec copy temp.mp4"

output,error = subprocess.Popen(command, universal_newlines=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).communicate()

Когда я это сделаю, ffmpeg не будет использовать другой способ, кроме кавычек вокруг concat segement. Есть ли способ успешно передать эту строку в команду subprocess.Popen?

4b9b3361

Ответ 1

Я бы предложил использовать форму списка, а не строку с кавычками:

command = ["ffmpeg", "-i", "concat:1.ts|2.ts", "-vcodec", "copy",
           "-acodec", "copy", "temp.mp4"]
output,error  = subprocess.Popen(
                    command, universal_newlines=True,
                    stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()

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

Тем не менее, если вы абсолютно хотите использовать версию простой строки, просто используйте разные кавычки (и shell=True):

command = 'ffmpeg -i "concat:1.ts|2.ts" -vcodec copy -acodec copy temp.mp4'
output,error  = subprocess.Popen(
                    command, universal_newlines=True, shell=True,
                    stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()

Ответ 2

Это работает с python 2.7.3. Команда для передачи stderr в stdout изменилась с более ранних версий python:

Поместите это в файл с именем test.py:

#!/usr/bin/python
import subprocess

command = 'php -r "echo gethostname();"'
p = subprocess.Popen(command, universal_newlines=True, shell=True, 
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
text = p.stdout.read()
retcode = p.wait()
print text

Вызвать это:

python test.py

Он печатает мое имя хоста, которое apollo:

apollo

Прочтите руководство для подпроцесса: http://docs.python.org/2/library/subprocess.html

Ответ 3

Используйте одиночные кавычки 'around the "whole pattern"' для автоматического выхода из парных разрядов или явно "escape the \"double quotes\"". Ваша проблема не имеет отношения к Popen как таковой.

Просто для записи у меня была проблема, особенно с командой list, переданной в Popen, которая не сохраняла бы правильные двойные кавычки вокруг шаблона glob (то есть, что было предложено в принятый ответ) под Windows. Объединение списка в строку с помощью ' '.join(cmd), прежде чем передать его в Popen, решило проблему.

Ответ 4

Я работал с аналогичной проблемой, с запуском относительно сложной команды через ssh. У этого также было многократные двойные кавычки и одиночные кавычки. Потому что я передавал команду через python, ssh, powershell и т.д.

Если вместо этого вы можете просто преобразовать команду в сценарий оболочки и запустить сценарий оболочки через subprocess.call/Popen/run, эти проблемы исчезнут.

Поэтому, в зависимости от того, работаете ли вы в Windows, Linux или Mac, поместите в сценарий оболочки следующее (script.sh или script.bat)

ffmpeg -i "concat:1.ts|2.ts" -vcodec copy -acodec copy temp.mp4

Тогда вы можете запустить

import subprocess; subprocess.call('./script.sh'; shell=True)

Не нужно беспокоиться о одиночных кавычках и т.д.

Ответ 5

Также борется со строковым аргументом, содержащим пробелы и не желая использовать shell = True.

Решением было использование двойных кавычек для внутренних строк.

args = ['salt', '-G', 'environment:DEV', 'grains.setvals', '{"man_version": "man-dev-2.3"}']

try:
    p = subprocess.Popen(args, stdin=subprocess.PIPE
                             , stdout=subprocess.PIPE
                             , stderr=subprocess.PIPE
                        )
    (stdin,stderr) = p.communicate()
except (subprocess.CalledProcessError, OSError ) as err:
    exit(1)
if p.returncode != 0:
    print("Failure in returncode of command:")