首页 > 解决方案 > 通过子进程调用时程序抛出错误

问题描述

概括

我正在尝试通过子进程调用命令调用外部程序。当直接从终端调用时,我的程序运行良好。但是,当通过子进程调用时,程序会抛出错误。

细节

我正在尝试在 Python 中调用程序Zimpl。Zimpl 是一个读取模型文件以及两个输入文件并生成输出文件的程序。

当我通过命令行调用 Zimpl 时,输出如下:

****************************************************
* Zuse Institute Mathematical Programming Language *
* Release 3.3.2 Copyright (C)2012 by Thorsten Koch *
****************************************************
*   This is free software and you are welcome to   *
*     redistribute it under certain conditions     *
*      ZIMPL comes with ABSOLUTELY NO WARRANTY     *
****************************************************

Reading model.zpl
Reading parfile.par
Reading values.txt
Instructions evaluated: 103351
Name: model.zpl   Variables: 156   Constraints: 546   Non Zeros: 2280
Writing [model.lp]
Writing [model.tbl]

当我使用命令调用子进程库时:

s = subprocess.check_call(['zimpl', 'model.zpl'])
print(s)

这是我得到的:

****************************************************
* Zuse Institute Mathematical Programming Language *
* Release 3.3.2 Copyright (C)2012 by Thorsten Koch *
****************************************************
*   This is free software and you are welcome to   *
*     redistribute it under certain conditions     *
*      ZIMPL comes with ABSOLUTELY NO WARRANTY     *
****************************************************

Reading model.zpl
Reading parfile.par
Reading values.txt
*** Error 800: File model.zpl Line 24 : Symbol "VALUE" not initialised

*** ximize obj :   sum <i,j> in Particles : (x[i,j] *  VALUE[i,j]);
***                                                     ^^^
Traceback (most recent call last):
  File "./runscript.py", line 153, in <module>
    evaluateLevel(0, sublevels[0], values)
  File "./runscript.py", line 111, in evaluateLevel
    s = subprocess.check_call(['zimpl', 'model.zpl'])
  File "/Users/macbook/anaconda2/lib/python2.7/subprocess.py", line 541, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['zimpl', 'model.zpl']' returned non-zero exit status 1

在 Zimpl 模型文件中,启动 VALUE 的行是这样的:

param VALUE[Particles] := read "values.txt" as "<1n,2n> 3n";

换句话说,VALUE 是从文件中读取的。我什至去 Zimpl 的源代码查看错误“符号 .. 未初始化”何时发生。这是我发现的:

case SYM_ERR : /* should not happen */
               sprintf(errmsg, "Symbol \"%s\" not initialised\n", yytext);
               yyerror(errmsg);

我不知道为什么会这样。我的猜测是它可能与缓冲区或执行程序太快导致 Zimpl 没有时间读取 data.txt 文件有关。

它变得更加有趣.. 如果我调用 Popen 命令并打印输出,则程序仅部分运行。

proc = subprocess.Popen(["zimpl",
                    "model.zpl"],
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    universal_newlines=True,
                    bufsize=0)
proc.wait() # I tried with and without this line, same output

for line in proc.stdout:
    print(line),

****************************************************
* Zuse Institute Mathematical Programming Language *
* Release 3.3.2 Copyright (C)2012 by Thorsten Koch *
****************************************************
*   This is free software and you are welcome to   *
*     redistribute it under certain conditions     *
*      ZIMPL comes with ABSOLUTELY NO WARRANTY     *
****************************************************

Reading model.zpl
Reading parfile.par
Reading values.txt

尽管现在它没有抛出错误,但没有像预期的那样生成文件。现在..如果我不尝试通过删除行来打印标准输出:

for line in proc.stdout:
    print(line),

瞧!!虽然我没有看到程序的输出,但文件已生成。为什么会发生这种情况?我没有提到我尝试过的所有事情,例如玩弄参数、尝试不同的 buffsize、使用子进程库中的其他命令等。其他都没有用。如果我想看到我的程序的输出,我不能。

最后,如果我运行命令:

proc = subprocess.Popen(["zimpl",
                    "model.zpl"],
                    stdin=subprocess.PIPE,
                 #   stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    universal_newlines=True,
                    bufsize=0)

这会正确生成输出和文件,但程序挂起并等待输入:

****************************************************
* Zuse Institute Mathematical Programming Language *
* Release 3.3.2 Copyright (C)2012 by Thorsten Koch *
****************************************************
*   This is free software and you are welcome to   *
*     redistribute it under certain conditions     *
*      ZIMPL comes with ABSOLUTELY NO WARRANTY     *
****************************************************

Reading model.zpl
Reading parfile.par
Reading values.txt
MacBook-Pro:model macbookpro$ Instructions evaluated: 103351
Name: model.zpl   Variables: 156   Constraints: 546   Non Zeros: 2280
Writing [model.lp]
Writing [model.tbl]

如果有人能解释发生了什么并提出一种产生输出和文件并且程序正常终止而无需等待输入的方法,我将不胜感激。

标签: pythonsubprocess

解决方案


推荐阅读