Передача команд оболочки двойной кавычки в 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?
Ответы
Ответ 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:")