'Stopping python-shell if a script has an endless loop
I'm working on a Node.js application which accepts submitted Python code and runs test suites on those submissions. I've been using python-shell package to run Python within Node.js. When submissions fail or pass test cases, everything is fine. The problem appears when a Python script contains an endless loop. In this case the python-shell instance never terminates.
I've checked some of stack overflow already asked questions, such as How to set a time limit to run asynchronous function in node.js?, Start and Stop Python Script from NodeJS? and How can I stop PythonShell but nothing seems to deal with endless loops within scripts.
I want to terminate my judgeRoutine() if the promise is not resolved within several seconds. I've tried to use timeout and promises to address the problem but so far to no avail. I include the code that I have:
//judge.js
const {PythonShell} = require('python-shell')
const fs = require('fs');
function judgeRoutine(){
let output=""
return new Promise(function(resolve, reject){
PythonShell.run('./test.py', null,function(err, result){
if(err){
return err
}
output = result[1]
console.log(output)
//perform DB operations based on output value
return resolve(output)
})
setTimeout(function(){if (output===""){
return reject(new Error("Time out"));
}
else{
resolve(output)
}} ,1000)
})
.catch(err => console.log(err))
}
function runJudge(){
new Promise(function(resolve, reject){
//copy scripts into the folder
//solution2.py contains an endless loop
fs.copyFile('./submissions/solution2.py', './solution.py', (err) => {
if (err) throw err;
console.log('File was copied to destination');
});
fs.copyFile('./tests/test35345.py', './test.py', (err) => {
if (err) throw err;
console.log('File was copied to destination');
})
}).then(judgeRoutine()).then(value => console.log("resolve value", value)).catch(err=> {if (err.name==="Time out"){
reject("Time out")
}})
}
module.exports={runJudge}
I would be happy to get any suggestions.
Solution 1:[1]
I included the code snippet that I used to stop an infinite loop in a python script that in running on my Node.js server.
Here I just created a simple promise to run the python script asynchronously to not to block the main thread. But I also added a removeEventlistener function that will stop running the python script after a certain number of time. You can adjust the value as per your need.
Also, you might have noticed that I didn't use any third party library and instead used the one built into Node js. Anyway, hope that it will give you an idea as to how to stop long running process of python scripts in Node.js
const pythonPromise = () => {
return new Promise((resolve, reject) => {
const python = spawn("python", ["./script.py"]);
const print = (data) => {
console.log(data.length);
console.log(data);
resolve(data.toString());
};
python.stdout.on("data", print);
setTimeout(() => {
python.stdout.off("data", print);
resolve("Infinite code detected");
}, 5000);
python.stderr.on("data", (data) => {
reject(data.toString());
});
});
};
async function runCode() {
const value = await pythonPromise().catch(console.log);
console.log(value);
}
runCode()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | hmShuvo_314 |