首页 > 解决方案 > 如何组织应该在多行上的 cmd 参数?

问题描述

被调用的程序需要在多行上提供参数,例如

some_program par0_1 par0_2 << EOF > out.log
par1_1 par1_2 par1_3 par1_4 
par2_1 par2_2 
par3_1 par3_2 par3_3 
par4_1
quit
EOF

到目前为止,我只在shell=True(subprocess.Popen()、subprocess.call()、os.system() 等方面都取得了成功)。我所做的是编写一个“参数”文件并将内容组织成

'cmd <参数>>日志2>&1'

并让 shell 来解释它。例如:

import subprocess
cmd = 'some_program'
settings = 'par0_1 par0_2'
cmd += settings
arg = ['par1_1 par1_2 par1_3 par1_4', 
       'par2_1 par2_2', 
       'par3_1 par3_2 par3_3', 
       'par4_1', 
       'quit']
with open('parameters', 'wt') as f:
    f.write('\n'.join(arg))
cmd += ' < parameters >> out.log 2>&1'
subprocess.call('cmd', shell=True) 

但我真的很想知道如何使用shell=False. 尝试了很多东西,但只要我把东西整理成一个清单,那就有问题了。使用subprocess.communicate()来提供类似的参数stdin可能会起作用(虽然会很笨重)。但是如果有人有一个更简单、更优雅的解决方案,我真的很感激——许多用 Fortran 编写的程序都要求这样的参数,我希望人们已经有了一个shell=False方便的解决方案。

标签: pythonsubprocess

解决方案


您当前在 shell 中使用的构造称为Here Document ,它只会导致数据通过 bash on stdin提供给进程。

它可以通过subprocess.Popen.communicate以下方式轻松复制:

from subprocess import Popen, PIPE, STDOUT

# here is the command and arguments, along with data for stdin
cmd = ['some_program', 'arg_0', 'arg_1']
lines = ['par1_1 par1_2 par1_3 par1_4',
         'par2_1 par2_2',
         'par3_1 par3_2 par3_3',
         'par4_1',
         'quit']

# create the process - in this example redirect stderr to stdout
process = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT)

# feed it the lines on stdin and get back the contents of stdout and stderr
stdout, stderr = process.communicate('\n'.join(lines))
print stdout

例如:

>>> process = Popen(["cat"], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
>>> stdout, stderr = process.communicate('\n'.join(['hello there', 'VXtal']))
>>> print stdout
hello there
VXtal

推荐阅读