将python中的双引号shell命令传递给subprocess.Popen()?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14928860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:53:18  来源:igfitidea点击:

Passing double quote shell commands in python to subprocess.Popen()?

pythonsubprocess

提问by Fight Fire With Fire

I've been trying to pass a command that works in shell that only works with literal double quotes in the commandline around the "concat:file1|file2"argument for ffmpeg.

我一直在尝试传递一个在 shell 中工作的命令,该命令仅适用于命令行"concat:file1|file2"中 ffmpeg 参数周围的文字双引号。

I cant however make this work from python with subprocess.Popen(). Anyone have an idea how one passes quotes into subprocess.Popen?

但是,我无法使用subprocess.Popen(). 任何人都知道如何将引号传递给 subprocess.Popen?

Here is the 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()

When I do this, ffmpeg won't take it any other way other than quotes around the concat segement. Is there a way to successfully pass this line to subprocess.Popen command?

当我这样做时,除了在 concat 段周围引用引号之外,ffmpeg 不会采取任何其他方式。有没有办法成功地将此行传递给 subprocess.Popen 命令?

采纳答案by Amber

I'd suggest using the list form of invocation rather than the quoted string version:

我建议使用列表形式的调用而不是引用的字符串版本:

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()

This more accurately represents the exact set of parameters that are going to be passed to the end process and eliminates the need to mess around with shell quoting.

这更准确地表示将要传递到最终进程的确切参数集,并消除了与 shell 引用混淆的需要。

That said, if you absolutely want to use the plain string version, just use different quotes (and shell=True):

也就是说,如果您绝对想使用纯字符串版本,只需使用不同的引号(和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()

回答by Eric Leschinski

This works with python 2.7.3 The command to pipe stderr to stdout has changed since older versions of python:

这适用于 python 2.7.3 自旧版本的 python 以来,将 stderr 管道传输到 stdout 的命令已更改:

Put this in a file called test.py:

把它放在一个名为 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

Invoke it:

调用它:

python test.py

It prints my hostname, which is apollo:

它打印我的主机名,即 apollo:

apollo

Read up on the manual for subprocess: http://docs.python.org/2/library/subprocess.html

阅读子流程手册:http: //docs.python.org/2/library/subprocess.html

回答by j08lue

Either use single quotes 'around the "whole pattern"'to automatically escape the doubles or explicitly "escape the \"double quotes\"". Your problem has nothing to do with Popenas such.

要么使用单引号'around the "whole pattern"'自动转义双打或显式"escape the \"double quotes\"". 你的问题与此无关Popen

Just for the record, I had a problem particularly with a list-based command passed to Popenthat would notpreserve proper double quotes around a glob pattern (i.e. what was suggested in the accepted answer) under Windows. Joining the list into a string with ' '.join(cmd)before passing it to Popensolved the problem.

只是为了记录在案,我特别有问题list传递给基础的命令Popen,将不会保留周围的glob模式适当双引号(即什么是在建议接受的答案在Windows下)。' '.join(cmd)在传递它之前将列表加入一个字符串以Popen解决问题。

回答by alpha_989

I have been working with a similar issue, with running a relatively complex command over ssh. It also had multiple double quotes and single quotes. Because I was piping the command through python, ssh, powershelletc.

我一直在处理类似的问题,通过 ssh 运行一个相对复杂的命令。它还具有多个双引号和单引号。因为我管道命令通过pythonsshpowershell等。

If you can instead just convert the command into a shell script, and run the shell script through subprocess.call/Popen/run, these issues will go away.

如果您可以将命令转换为 shell 脚本,然后通过 运行 shell 脚本subprocess.call/Popen/run,这些问题就会消失。

So depending on whether you are on windows or on linux or mac, put the following in a shell script either (script.shor script.bat)

因此,根据您是在 windows 上还是在 linux 或 mac 上,将以下内容放入 shell 脚本中(script.shscript.bat

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

Then you can run

然后你可以运行

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

Without having to worry about single quotes, etc.

无需担心单引号等。

回答by Pieter

Also struggling with a string argument containing spaces and not wanting to use the shell=True.

还挣扎于包含空格的字符串参数并且不想使用shell=True

The solution was to use double quotes for the inside strings.

解决方案是对内部字符串使用双引号。

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:")