Python 使用包含引号的参数的subprocess.run

Python 使用包含引号的参数的subprocess.run,python,python-3.x,Python,Python 3.x,我尝试运行的命令如下所示: xvfb run--auto-servernum--server args=“-screen 0 640x480x24”--错误文件=/dev/stdout/opt/myExecutable 这就是我在Python3中所做的: args=['xvfb-run'、'-auto-servernum'、'-server args=“-screen 0 640x480x24”、'-error file=/dev/stdout'、'/opt/myExecutable'] 命令

我尝试运行的命令如下所示:

xvfb run--auto-servernum--server args=“-screen 0 640x480x24”--错误文件=/dev/stdout/opt/myExecutable
这就是我在Python3中所做的:

args=['xvfb-run'、'-auto-servernum'、'-server args=“-screen 0 640x480x24”、'-error file=/dev/stdout'、'/opt/myExecutable']
命令=''.join(xvfbArgs)
打印(f'Command:{Command}')
子流程运行(xvfbArgs)
我得到以下信息:

Unrecognized option: "-screen
use: X [:<display>] [option]
...
segfault
...
Command: xvfb-run --auto-servernum --server-args="-screen 0 640x480x24" --error-file=/dev/stdout /opt/myExecutable
无法识别的选项:“-屏幕
使用:X[:][选项]
...
断层
...
命令:xvfb run--auto-servernum--server args=“-screen 0 640x480x24”--错误文件=/dev/stdout/opt/myExecutable
打印的命令是正确的

我还尝试了使用
“-server args=”-screen 0 640x480x24'
(倒置的
,这导致了相同的结果(
无法识别的选项:“-screen


子流程中运行的
更改了
--server args=“-screen 0 640x480x24”

正确的语法是:

args = [
    'xvfb-run',
    '--auto-servernum',
    '--server-args=-screen 0 640x480x24',
    '--error-file=/dev/stdout',
    '/opt/myExecutable'
]

try:
    from pipes import quote  # Python 2
except ImportError:
    from shlex import quote  # Python 3

command_str = ' '.join(quote(s) for s in args)
print(f'Command: {command_str}')

subprocess.run(args) # or subprocess.run(command_str, shell=True)

请注意,这里根本没有文字引号——唯一的引号是Python语法。在bash中,未转义引号是语法,而不是数据,即使它们存在于字符串中。

只是不要将命令合并到字符串中,然后不要将引号放在原来的位置,以保护字符串不受shell的影响

args = ['xvfb-run', '--auto-servernum','--server-args=-screen 0 640x480x24', '--error-file=/dev/stdout', '/opt/myExecutable']
print(f'Command: {args}')
subprocess.run(args)

下面是一种简单的方法,可以告诉您传递给
subprocess.run
的命令应该是什么样子。在shell(不是Python,一个常规shell)中,在要运行的命令之前插入
Python-c“import sys;print(sys.argv[1:])”

19:59 ~ $ python -c 'import sys; print(sys.argv[1:])' xvfb-run --auto-servernum --server-args="-screen 0 640x480x24" --error-file=/dev/stdout /opt/myExecutable
['xvfb-run', '--auto-servernum', '--server-args=-screen 0 640x480x24', '--error-file=/dev/stdout', '/opt/myExecutable']

结果列表正是您应该传递给
子流程的内容。运行
。在这里,我们可以看到shell将输入中的
--server args=“-screen 0 640x480x24”
转换为一个没有引号的单参数。

--server args=“-screen 0 640x480x24”
在bash中完全等同于
“--服务器参数=-屏幕0 640x480x24"
。引号是按字符逐个计算的bash语法,而不是传递给
xvfb run
的数据,因此不应该在数据中添加任何文字引号。OP继续将参数合并到单个字符串中,因此它们毕竟需要一些引号。但当然,更好的解决方案是保留参数作为列表。为了向用户打印,它们正在合并为字符串。最好使用
shlex.quote()
对于该作业,生成与shell所需格式相同的内容。@tripleee我合并到一个数组中,以查看要运行的命令。我错过了
subprocess.run
引用我的参数的部分,因为其中有一个空格。@Nepoxx,…也就是说,当您运行
xvfb run--server args时=“-screen0640x480x24”
在bash中,它成为指向C字符串的指针数组,也可以描述为
char**{“xvfb run”,“--server args=-screen0640x480x24”,NULL}
--这些字符串中的任何地方都没有引号;当shell认为引号意味着
640x480x24
应该与
--server args=
@Nepoxx在同一个参数中时,这些引号被shell使用和删除了,“任何必需的转义”都可能导致在某些平台上(即所有非Windows系统)实际上不需要转义。有关基本操作系统调用集的手册,请参阅
man2execve