繁体   English   中英

将变量传递给 Subprocess.Popen

[英]Passing Variables to Subprocess.Popen

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

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

我无法执行命令

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)

放下shell=True 如果shell=True则在Unix上对Popen()的参数进行不同的处理

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

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

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

在您的情况下,您需要将其拆分为以下内容:

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)

这是因为,如果您传递一个列表, Popen假定您已经将命令行分割成多个单词(这些值最终会出现在sys.argv ),因此不需sys.argv

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

解决该问题的另一种方法是将所有单词连接到一个字符串中(然后Popen将拆分它-请参见subprocess.list2cmdline )。 但是,如果可能的话,最好使用列表版本-它可以更轻松地控制命令行的分割方式(例如,如果参数中包含空格或引号),而不必弄乱引号引起来。

第一个Popen参数的类型为str问题。 将其替换为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

如果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)

注意1shell=True构造command可能不安全。 使用pipes.quote()减少注入的可能性。
注2 :从python2不推荐使用pipes.quote() 对于python3使用shlex模块。

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

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)

用例

运行n个shell脚本或python脚本

创建一个 run.py 文件,负责将参数(整数)传递给 shell 文件。

假设您喜欢运行 n(4) 个接受1 个参数的 shell 脚本或 python 脚本。

使用以下代码创建文件run.python

下面的代码说明

  • instanceQty = 要运行的 shell 脚本的数量
  • os.getcwd() = 当前文件的路径
  • mockScript.sh = 我和run.py放在同一个目录下的shell 脚本

运行 shell 脚本

# this is python file with name run.py
import subprocess,os
instanceQty = 4
for i in range(0, instanceQty):
    print(os.getcwd())
    subprocess.Popen(f"{os.getcwd()}/mockScript.sh {i}",shell=True,executable='/bin/bash')

运行python脚本

import subprocess,os,sys
instanceQty = 4
for i in range(0, instanceQty):
    print(os.getcwd())
    subprocess.Popen([sys.executable,f"{os.getcwd()}/mockScript.py",str(i)])
    

运行这个文件

蟒蛇运行.py

MacOS 上的权限问题

须藤 chmod ug+x mockScript.sh

须藤 chmod ug+x run.py

所有代码都在 Python 3.8.1 和 MacOs 12.0.1 环境中测试过。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM