J'ai essayé de passer une commande qui fonctionne dans Shell et qui ne fonctionne qu'avec des guillemets doubles littéraux dans la ligne de commande autour de l'argument "concat:file1|file2"
pour ffmpeg.
Je ne peux cependant pas faire ce travail à partir de python avec subprocess.Popen()
. Quelqu'un a une idée de la façon dont on passe des guillemets dans subprocess.Popen?
Voici le code:
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()
Quand je le ferai, ffmpeg ne le prendra pas autrement que par des guillemets autour du segment. Est-il possible de passer cette ligne avec succès à la commande subprocess.Popen?
Je suggérerais d'utiliser la forme de liste d'invocation plutôt que la version de chaîne citée:
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()
Cela représente plus précisément l'ensemble exact des paramètres qui vont être transmis au processus final et élimine le besoin de perdre du temps avec les citations Shell.
Cela dit, si vous voulez absolument utiliser la version chaîne, utilisez simplement des guillemets différents (et 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()
Cela fonctionne avec python 2.7.3 La commande de rediriger stderr vers stdout a été modifiée depuis les anciennes versions de python:
Mettez ceci dans un fichier appelé 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
Invoquez-le:
python test.py
Il affiche mon nom d’hôte, qui est apollo:
apollo
Consultez le manuel du sous-processus: http://docs.python.org/2/library/subprocess.html
Utilisez des guillemets simples 'around the "whole pattern"'
pour échapper automatiquement aux doublons ou explicitement "escape the \"double quotes\""
. Votre problème n'a rien à voir avec Popen
en tant que tel.
Pour mémoire, j’ai eu un problème particulier avec une commande list
-based passée à Popen
qui conserverait non les guillemets doubles appropriés autour d’un motif glob (c’est-à-dire ce qui était suggéré dans réponse acceptée ) sous Windows. Joindre la liste dans une chaîne avec ' '.join(cmd)
avant de la transmettre à Popen
a résolu le problème.
Je travaille avec un problème similaire, avec l'exécution d'une commande relativement complexe Sur ssh. Il y avait aussi des guillemets doubles et des guillemets simples. Parce que Je transmettais la commande à travers python
, ssh
, powershell
etc.
Si, au lieu de cela, vous pouvez simplement convertir la commande en script Shell et exécuter le scriptShell via subprocess.call/Popen/run
, ces problèmes disparaîtront.
Donc, selon que vous utilisiez Windows, Linux ou Mac, placez le Suivant dans un script Shell (script.sh
ou script.bat
)
ffmpeg -i "concat:1.ts|2.ts" -vcodec copy -acodec copy temp.mp4
Ensuite, vous pouvez courir
import subprocess; subprocess.call(`./script.sh`; Shell=True)
Sans avoir à vous soucier des guillemets simples, etc.
Également en conflit avec un argument de chaîne contenant des espaces et ne souhaitant pas utiliser Shell = True.
La solution consistait à utiliser des guillemets doubles pour les chaînes internes.
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:")