Python 将变量传递给 Subprocess.Popen

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20140137/
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 19:39:42  来源:igfitidea点击:

Passing Variables to Subprocess.Popen

pythonsubprocess

提问by GaNi

I have a script which calls another python script by subprocess.Popen module. But since I have arguments stored in variable(s)

我有一个脚本,它通过 subprocess.Popen 模块调用另一个 python 脚本。但是因为我有参数存储在变量中

servers[server]['address']
servers[server]['port']
servers[server]['pass']

I am unable to perform the command

我无法执行命令

p = subprocess.Popen(["python mytool.py -a ", servers[server]['address'], "-x", servers[server]['port'], "-p", servers[server]['pass'], "some additional command"], shell=True, stdout=subprocess.PIPE)

采纳答案by jfs

Drop shell=True. The arguments to Popen()are treated differently on Unix if shell=True:

下降shell=True在 Unix 上,的参数Popen()被区别对待,如果shell=True

import sys
from subprocess import Popen, PIPE

# populate list of arguments
args = ["mytool.py"]
for opt, optname in zip("-a -x -p".split(), "address port pass".split()):
    args.extend([opt, str(servers[server][optname])])
args.extend("some additional command".split())

# run script
p = Popen([sys.executable or 'python'] + args, stdout=PIPE)
# use p.stdout here...
p.stdout.close()
p.wait()

Note that passing shell=Truefor commands with external input is a security hazard, as described by a warning in the docs.

请注意,传递shell=True带有外部输入的命令是一种安全隐患,如docs 中的警告所述

回答by babbageclunk

When you call subprocess.Popenyou can pass either a string or a list for the command to be run. If you pass a list, the items should be split in a particular way.

当您调用时,subprocess.Popen您可以传递一个字符串或一个列表来运行命令。如果您传递一个列表,则应以特定方式拆分项目。

In your case, you need to split it something like this:

在你的情况下,你需要像这样拆分它:

command = ["python",  "mytool.py", "-a", servers[server]['address'], 
           "-x", servers[server]['port'], 
           "-p", servers[server]['pass'], 
           "some",  "additional", "command"]
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)

This is because if you pass in a list, Popenassumes you have already split the command line into words (the values that would end up in sys.argv), so it doesn't need to.

这是因为如果您传入一个列表,则Popen假定您已经将命令行拆分为单词(以 结尾的值sys.argv),因此不需要这样做。

The way you're calling it, it will try to run a binary called "python mytool.py -a", which isn't what you meant.

你调用它的方式,它会尝试运行一个名为“python mytool.py -a”的二进制文件,这不是你的意思。

The other way to fix it is to join all of the words into a string (which Popenwill then split up - see subprocess.list2cmdline). But you're better off using the list version if possible - it gives simpler control of how the commandline is split up (if arguments have spaces or quotes in them, for example) without having to mess around with quoting quote characters.

修复它的另一种方法是将所有单词连接成一个字符串(然后Popen将拆分 - 请参阅subprocess.list2cmdline)。但是,如果可能,您最好使用列表版本 - 它可以更简单地控制命令行的拆分方式(例如,如果参数中有空格或引号),而不必乱用引号字符。

回答by ciphor

You should concatenate the command to a whole string:

您应该将命令连接到整个字符串:

p = subprocess.Popen("python mytool.py -a " + servers[server]['address'] + " -x " + servers[server]['port'] + " -p " + servers[server]['pass'] + " some additional command", shell=True, stdout=subprocess.PIPE)

回答by Michael Kazarian

Your problem in type strfor first Popenargument. Replace it to list. Below code can work:

str的第一个Popen参数的类型问题。将其替换为list. 下面的代码可以工作:

address = servers[server]['address']
port = servers[server]['port']
pass = servers[server]['pass']

command = "python mytool.py -a %s -x %d -p %s some additional command" % (address, port, pass)
p = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
#        it is a list^^^^^^^^^^^^^^^  shell=False

If commandarguments get from a trusted source you can construct commandand use it with shell=Trueto such manner:

如果command参数来自可信来源,您可以以这种方式构建command和使用它shell=True

import pipes as p
command = "python mytool.py -a {} -x {} -p {} some additional command".format(p.quote(address), p.quote(port), p.quote(pass))
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)

Note 1: constructed commandwith shell=Trueis potentially insecure. Use pipes.quote()for reduce injection possibility.
Note 2: pipes.quote()deprecated since python2; for python3use shlexmodule.

注 1:构造commandwithshell=True可能不安全。使用pipes.quote()用于减少注射的可能性。
注 2pipes.quote()已弃用python2;用于python3使用shlex模块。