从超时运行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()',我没有足够的声望。
一个简单的解决方案可以是使用迄今为止找到的所有解决方案,但不是一次运行程序,而是多次运行它们。
一次,以确定运行时间, 另一个时间,以确定输出 等 这样,你也可以测试是否给他们提供相同的输出相同的输入。 它可能不是您正在寻找的“超级优雅”解决方案,但现在可能已经足够,直到您在python中找到子进程的圣杯。
此外,您可以将输出重定向到文件以获得部分结果+超时,然后读取部分结果的文件。
基于@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()
你在使用什么操作系统? – unutbu
我目前正在我的Linux Mint 18.1笔记本电脑上运行,但此脚本旨在运行在学校的Ubuntu 16.04服务器上。 – Elman
带有'timeout'的'subprocess.call()'在异常处理程序中调用'p.kill()'和'p.wait()',如果超时过期,则调用该异常处理程序。因此,它实际上杀死了立即产生的进程。 –