如何在Node.js中同步运行Python脚本?

6

我通过python-shell在Node.js中运行以下Python脚本:

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"

而我的相应的Node.js代码是:

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

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

输出结果为:

Now reading data
finished

但是预期输出结果应该是:
finished 
Now reading data

Node.js无法同步执行我的Python脚本,它会先执行PythonShell.run函数后面的所有代码,然后再执行PythonShell.run。我该如何先执行PythonShell.run,再执行后续代码?非常感谢您的帮助...这是一个紧急情况!


node.js 的主要设计目标是异步运行任务。您能否详细说明为什么需要异步? - Klaus D.
实际上,我正在使用一个颜色检测传感器。颜色检测是通过Python脚本完成的。根据检测到的颜色,我需要使用Node.js进行一些其他计算。我正在处理一个大项目,颜色检测是我的任务之一,使用Python很容易检测颜色,但其他计算需要使用Node.js完成。 - Ramzan
4个回答

3
对我很有效:
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');

结果是:
start ...
... end main
PythonShell results: ["Hello World!"]
python call ends
The result is: Hello World!
end runTest()

1

我遇到了同样的问题,并通过在PythonShell.run方法内部创建一个promise来解决它。然后,您只需要等待该promise,您的代码就会同步运行。

promisify方法:

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();
    }
  })
},

然后,你等待 promise:
await RunPythonScript(YOURscriptPath,YOURargsScript,YOURpythonFile); 

这太棒了。util.promisify也可以压缩一下! - jboxxx

0

由于这是异步操作,请添加一个结束回调函数(可以在文档中找到)而不是在顶层添加指令。

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

我已经尝试过这个:如果在'pyshell.end(){}'函数后面还有任何代码,那么程序会先执行以下代码,然后再执行'pyshell.end(){}'。但是我需要'pyshell.end(){}'先被执行,然后才执行下面的代码。 - Ramzan
1
我认为你误解了 Klaus D. 最初的陈述:这是一个异步系统。你的“下面的代码”必须在 pyshell.end 回调函数中。不能阻塞主程序。就像在图形界面中添加按钮一样,你必须连接一个回调函数来响应当有人点击它时,但主循环仍然保持自由。 - Jean-François Fabre

-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();
              });
              
            }
        }
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接