从超时运行python的可执行文件

从超时运行python的可执行文件

问题描述:

我很长一段时间的读者,但这是我的第一个问题。
我正在编写一个Python 3程序(我目前正在自学)编译和运行一组C++程序,该程序应该做同样的事情(学生为作业提交)并将其输出与我在文本文件中已经有了预期的输出。从超时运行python的可执行文件

我正在寻找一种方式来运行这些可执行文件,允许我:

  • 在一定时限内终止后的可执行文件(比如,10秒),如果它没有结束。
  • 捕获可执行文件的所有输出(包括stdout,stderr和任何“shell”消息,如分段错误,内存/内核转储等..)
  • 即使可执行文件崩溃或被强制终止超过允许的时间后),我需要捕获到那个点的“部分”输出。
  • 没有任何内容出现在屏幕上(没有输出或错误消息)。

我到目前为止试过的一切(从类似问题的答案中)都缺少了一些东西。我找不到满足我所有需求的东西(上述要点)。 下面是一些例子:

  • check_output()(如在this问题)不会收集输出,如果可执行崩溃,而有些信息(如核心转储)还是去到屏幕上。

  • Popen()(如this)似乎不会终止可执行文件(超过时间时)。 Python线程结束(我希望我在这里使用正确的术语),但可执行文件保持运行。

  • 即使像os.system()这样的方法不鼓励,但我试过它们,他们没有更好的表现。

我非常感谢它,如果有人能指出我的方式来实现这一点。我对任何语法错误表示歉意,因为英语不是我的第一语言。请让我知道是否需要任何进一步的细节。 谢谢

编辑:

这里是我的Python代码最小副本:

from subprocess import STDOUT, check_output, TimeoutExpired 

timeLimit = 3 # seconds 
strOutput = '' 

try: 
    output = check_output('./a.out', stderr = STDOUT, timeout = timeLimit) 
    strOutput = ''.join(map(chr, output)) 

except TimeoutExpired as e: 
    strOutput += 'Error: Time limit exceeded, terminated..' 

except Exception as e: 
    strOutput += 'Error: ' + str(e) 

f = open('report.txt','w') 
f.write(strOutput) 
f.close() 

我还包括一些C++的样品含有一些错误,以创建可执行文件使用测试以前的代码。 它们都可以被编译为:克++ programName.cpp

#include <iostream> 
using namespace std; 

int main() 
{ 
    cout << "This one is working correctly!" << endl; 
} 

下面的代码“被零除”错误导致。该错误之前打印的语句不是由check_output()

#include <iostream> 
using namespace std; 

int main() 
{ 
    cout << "Trying to divide by zero.." << endl; 
    cout << 3/0 << endl; 
} 

此代码等待一个意想不到的输入(应该由脚本指定的超时之后终止)捕获

#include <iostream> 
using namespace std; 

int main() 
{ 
    int x; 
    cout << "Waiting for an unexpected input.." << endl; 
    cin >> x; 
} 

我不能找到可靠的方法来重现核心转储问题。核心转储是一个特殊情况,因为check_output()无法捕获其输出(它直接/仅显示在屏幕上)。

P.S.我无法添加标签'check_output()',我没有足够的声望。

+1

你在使用什么操作系统? – unutbu

+0

我目前正在我的Linux Mint 18.1笔记本电脑上运行,但此脚本旨在运行在学校的Ubuntu 16.04服务器上。 – Elman

+0

带有'timeout'的'subprocess.call()'在异常处理程序中调用'p.kill()'和'p.wait()',如果超时过期,则调用该异常处理程序。因此,它实际上杀死了立即产生的进程。 –

一个简单的解决方案可以是使用迄今为止找到的所有解决方案,但不是一次运行程序,而是多次运行它们。

一次,以确定运行时间, 另一个时间,以确定输出 等 这样,你也可以测试是否给他们提供相同的输出相同的输入。 它可能不是您正在寻找的“超级优雅”解决方案,但现在可能已经足够,直到您在python中找到子进程的圣杯。

此外,您可以将输出重定向到文件以获得部分结果+超时,然后读取部分结果的文件。

+0

谢谢你的回答。运行时间实际上不是问题。我只用它来避免无限循环的程序。我的主要问题是捕获*全部*输出。我无法找到一种方法将输出重定向到使用check_output()的文件,所以我很感激你能否指出我的一个实际例子(我对Python比较新)。 – Elman

+0

这是我正在尝试(重定向到一个文件)'output = check_output(['./a.out','> report.txt'],stderr = STDOUT,timeout = timeLimit)' – Elman

+0

也许只是运行一个运行其代码的bash脚本。 –

基于@CharlesDuffy评论,我简化了流程树使其更加平滑,并切换到subprocess.call(),它具有捕获“部分”输出(在可执行文件崩溃之前)的优势。
然而核心转储仍然没有被subprocess.call()捕获,它会进入屏幕。
有什么办法来捕获核心转储的输出?或者至少是为了防止它在屏幕上显示?

from subprocess import call, TimeoutExpired 

timeLimit = 3 # seconds 
errMsg = '' 
ret_code = 0 
f = open('report.txt','w') 

try: 
    ret_code = call('./a.out', stdout = f, stderr = f, timeout = timeLimit) 

except TimeoutExpired as e: 
    errMsg = 'Error: Time limit exceeded, terminating..' 

except Exception as e: 
    errMsg = 'Error: ' + str(e) 

if ret_code: 
    errMsg = 'Error: ' + str(ret_code) 

f.write(errMsg) 
f.close()