4

I have the following code. Where i upload the file first and then i read the file and console the output like console.log(obj). But the response comes first and the python scripts runs behind the scene. How can i make code to wait for the python script to run then proceed?

router.post(`${basePath}/file`, (req, res) => {

    //Upload file first

    PythonShell.run('calculations.py', { scriptPath: '/Path/to/python/script' }, function (err) {
        console.log(err);
        let obj = fs.readFileSync('Path/to/file', 'utf8');
        console.log(obj);
    });

    return res.status(200).send({
        message : 'Success',
    });
});

I cannot get console.log(obj); output because it runs after the response. How can i make it wait for the python script to run and get console.log(obj) output on console.

11
  • 1
    Try to move res.status(200).send at the end of the third PythonShell.run argument callback's body. This will send a 200-response after the script is done. Commented Nov 15, 2017 at 5:16
  • Do you want to respond script's running result on that POST request? And do you see the result of console.log(obj) in the console output? Commented Nov 15, 2017 at 5:26
  • @dhilt No i cannot see the output of console.log(obj) in the console. And i want to return response as the output of console.log(obj). Commented Nov 15, 2017 at 5:28
  • Okey, I've just tried to give an answer. Commented Nov 15, 2017 at 5:51
  • 1
    from the code i can only see let obj = fs.readFileSync('Path/to/file', 'utf8'); is not working , check for file is there is content or file , if there is no content then only this would be an error . Please debug that once . Commented Nov 15, 2017 at 6:12

1 Answer 1

5

To return the result after some async operation, you should call res.send inside the done-callback.

router.post(`${basePath}/file`, (req, res) => {

    //Upload file first

    PythonShell.run('calculations.py', { scriptPath: '/Path/to/python/script' }, function (err) {
        console.log('The script work has been finished.'); // (*)
        if(err) {
          res.status(500).send({
            error: err,
          });
          console.log(err);
          return;
        }
        let obj = fs.readFileSync('Path/to/file', 'utf8');
        console.log(obj); // (**)
        res.status(200).send({
            message : 'Success',
        });
    });
});

Then if you will not see the log (*) in the console, then it would mean that the script does not work or works improperly. The callback is not being called. First of all, you need to be sure that the script (PythonShell.run) works and the callback is being called. The POST handler will wait until you call res.send (with no matter of delay value), so that callback is the main point.

Also readFileSync could fail. In case of readFileSync failure you should see an exception. If it's ok then you'll see the next log (**) and the response will be sent.


I see PythonShell in your code. I have no experience with it, but after some reading I think that the problem could be in how you are using it. It seems the python-shell npm package, so following it's documentation you may try to to instantiate a python shell for your script and then to use listeners:

let pyshell = new PythonShell('calculations.py');

router.post(`${basePath}/file`, (req, res) => {
  pyshell.send(settings); // path, args etc
  pyshell.end(function (err) {
    console.log('The script work has been finished.');
    if(err) { res.status(200).send({ error: err }); }
    else { res.status(200).send({ message : 'Success' }); }
  });
});

This approach could be more appropriate because the pyton shell is kept open between different POST requests. This depends on your needs. But I guess it does not solve the problem of script running. If you are sure that the script itself is fine, then you need just to run it properly in the Node environment. There are some points:

  • path to script
  • arguments
  • other settings

Try to remove all arguments (create some new test script), cleanup settings object (keep only path) and execute it from Node. Handle its result in Node. You should be able to run the simplest script by correct path! Research how to setup correct scriptPath. Then add an argument to your script and run it with an argument. Hanlde the result again. There are not so many options, but each of them could be the cause of improper call.

Sign up to request clarification or add additional context in comments.

6 Comments

Great explanation, That make sense, But the above code is not returning response not showing any kind of message or output in the console.
After sending a request from the POSTMAN, with a file which is saving locally as expected etc, i haven't get anything except the route names after each call which is fine.
That means exactly that PythonShell.run does not work. I'm afraid I know nothing about such a script running, this is out of my competence. You need to debug PythonShell.run call.
I also think so .
The script i am running with PythonShell.run is fine becasue with that script i am creating file which is creating and python part is working fine. fs.readFileSync is to read the file which is there and works outside PythonShell.run() but do not work inside of it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.