6

I am running the following Python script in Node.js through python-shell:

import sys
import time
 x=0
 completeData = "";
 while x<800:
  crgb =  ""+x;
  print crgb
  completeData = completeData + crgb + "@";
  time.sleep(.0001)
  x = x+1
  file = open("sensorData.txt", "w")
  file.write(completeData)
  file.close()
  sys.stdout.flush()
else:
 print "Device not found\n"

And my corresponding Node.js code is:

var PythonShell = require('python-shell');

PythonShell.run('sensor.py', function (err) {
    if (err) throw err;
    console.log('finished');
});
console.log ("Now reading data");

Output is:

Now reading data
finished

But expected output is:

finished 
Now reading data

Node.js can not execute my Python script synchronously, it executes first all the code following the PythonShell.run function then executes PythonShell.run. How can I execute first PythonShell.run then the following code? Any help will be mostly appreciated... It is an emergency please!

2
  • The main design goal of node.js is to run task asynchronously. Can you please elaborate why it has to be asynchronously? Commented Aug 2, 2016 at 19:54
  • Actually, I am using a color detector sensor. The color detection is done by the python script. And based on the detected color I have to do some other calculations which are done using node.js. I am working with a big project and the color detection is the part of my tasks and it is very much easy to detect the color using python but other calculations need to be done using node.js Commented Aug 2, 2016 at 20:06

4 Answers 4

3

It work for me:

let {PythonShell} = require('python-shell');

var options = {
    mode:           'text',
    pythonPath:     'python',
    pythonOptions:  [],
    scriptPath:     '',
    args:           []
};

async function runTest()
{
    const { success, err = '', results } = await new Promise(
        (resolve, reject) =>
        {
            PythonShell.run('hello.py', options,
                function (err, results)
                {
                    if (err)
                    {
                        reject({ success: false, err });
                    }

                    console.log('PythonShell results: %j', results);

                    resolve({ success: true, results });
                }
            );
        }
    );

    console.log("python call ends");

    if (! success)
    {
        console.log("Test Error: " + err);
        return;
    }

    console.log("The result is: " + results);

    // My code here

    console.log("end runTest()");
}

console.log('start ...');

runTest();

console.log('... end main');

The result is:

start ...
... end main
PythonShell results: ["Hello World!"]
python call ends
The result is: Hello World!
end runTest()
Sign up to request clarification or add additional context in comments.

Comments

1

I had the same problem and resolved it by making a promise with the PythonShell.run method inside it. Then, you only have to await that promise and your code runs synchronously.

The promisify method:

RunPythonScript: function(scriptPath, args, pythonFile){
  let options = {
    mode: 'text',
    pythonPath: 'python',
    pythonOptions: [], 
    scriptPath: scriptPath,
    args: args,
  };

  return new Promise((resolve,reject) =>{
    try{
      PythonShell.run(pythonFile, options, function(err, results) {
        if (err) {console.log(err);}
        // results is an array consisting of messages collected during execution
        console.log('results', results);
        resolve();          
      }); 
    }
    catch{
      console.log('error running python code')
      reject();
    }
  })
},

Then, you await the promise:

await RunPythonScript(YOURscriptPath,YOURargsScript,YOURpythonFile); 

1 Comment

this is great. util.promisify could condense this a bit too!
0

As this is asynchronous, add an end callback (found in the documentation) instead of instructions at top level

// end the input stream and allow the process to exit 
pyshell.end(function (err) {
  if (err) throw err;
  console.log ("Now reading data");
});

2 Comments

I have tried this : If I have anymore code following 'pyshell.end(){}' function then the program execute first the following code then execute 'pyshell.end(){}' . But I need that 'pyshell.end(){}' need to be executed first then the following code
I think you misunderstood what Klaus D. stated at first: this is an asynchronous system. Your "following code" must be in the pyshell.end callback. Nothing must block the main program. It's just when you add a button in a graphical interface. You have to connect a callback to respond when someone clicks on it, but the main loop remains free.
-1

export default {
    data () {
            return {
            }
        },
        method: {
            callfunction () {
              console.log ("Now reading data");
            },
            pyth (){
              var PythonShell = require('python-shell');
              var vm = this; //save the object (this) in variable vm to use inside pythonshell.run
              PythonShell.run('sensor.py', function (err) {
                  if (err) throw err;
                  console.log('finished');
                  vm.callfunction();
              });
              
            }
        }
}

Comments

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.