2

我正在尝试编写一个 python 脚本,将字符串发送到程序并将其置于后台。在命令行上,我可以复制并粘贴以下代码并让它成功地完成我希望 python 程序执行的操作:

printf "f\nil\ncs\n1.e-8 100.0 1.e-8\nn\n0.002\nb\n0.05\nz\n2.e-7\nx4\n5.e-7\n\n\nfort.13\nn\nn\n\n" | vpfit95

其中:vpfit95是我的 PATH 中可执行程序的别名。

我尝试过的一些排列(一次尝试一个):

import subprocess
vpfitExecutable = 'vpfit95'

String1=r'f\nil\ncs\n1.e-8 100.0 1.e-8\nn\n0.002\nb\n0.05\nz\n2.e-7\nx4\n5.e-7\n\n\nfort.13\nn\nn\n\n'
String2=r"f\nil\ncs\n1.e-8 100.0 1.e-8\nn\n0.002\nb\n0.05\nz\n2.e-7\nx4\n5.e-7\n\n\nfort.13\nn\nn\n\n"
String3="f\nil\ncs\n1.e-8 100.0 1.e-8\nn\n0.002\nb\n0.05\nz\n2.e-7\nx4\n5.e-7\n\n\nfort.13\nn\nn\n\n"

cmd1 = "printf \"" + String1 + "\"" 
cmd2 = "printf \"" + String1 + "\" | " + vpfitExecutable 
cmd3 = "printf \"" + String2 + "\"" 
cmd4 = "printf \"" + String3 + "\"" 

print cmd2

p1 = subprocess.Popen([vpfitExecutable, cmd1])
p2 = subprocess.Popen([cmd2])
p3 = subprocess.Popen([vpfitExecutable, cmd3])
p4 = subprocess.Popen([vpfitExecutable, cmd4])
p4 = subprocess.Popen([vpfitExecutable, String1])
p5 = subprocess.Popen([vpfitExecutable, String2])
p6 = subprocess.Popen([vpfitExecutable, String3])

# check
p7 = subprocess.Popen([vpfitExecutable]) # works.

并且全部失败(p7除外)。有些因“Fortran 运行时错误:文件结尾”(来自 vpfit 程序)而失败。其他失败并返回到子进程库和“OSError:[Errno 2] 没有这样的文件或目录”。

一些检查:当我打印cmd2并将其复制并粘贴到终端时,它可以正常工作。当我运行时p7,它按预期正确开始运行程序,只是没有输入字符串。我显然在这里遗漏了一些基本的东西,我就是不知道是什么。任何帮助表示赞赏!

4

1 回答 1

6

是的,你缺少一些基本的东西——管道由外壳处理。要对子进程执行您想要的操作,您应该将其vpfit95作为子进程运行,然后再communicate使用它。请参阅文档的第 17.1.4.2 节,替换 shell pipeline

proc = subprocess.Popen([vpfitExecutable], stdin=subprocess.PIPE)
proc.communicate(input='your string') 

如果您需要检查 vpfit 的 stdout 和 stderr,请从communicate.

一个肮脏的替代方法是使用 运行你的命令shell=True,它在 shell 中生成它,然后你可以在你的命令中使用管道,但是“去掉中间人”并直接与子进程交互更干净。

于 2012-07-17T07:17:48.820 回答