如何执行Python脚本并检索Node.js中的输出(数据和错误)

本文概述

Node.js使用事件驱动的非阻塞I / O模型, 使其轻巧高效, 非常适合在分布式设备上运行的数据密集型实时应用程序, 但是很少有计算任务可供你使用Python如果你非常关注项目的速度。

但另一方面, 你可能仍想使用Node.js, 因此你需要学习如何从Node执行Python脚本。在这种情况下, 我们将介绍最基本的要点, 如如何执行Python脚本以及如何检索生成的输出(包括标准输出和错误输出)。

在继续本教程之前, 你需要执行python脚本。因此, 在本文中, 我们将使用以下python脚本(如果你手边没有任何脚本或想要测试, 可以使用它):

# script.py
my_name = 'Carlos'
my_age = 18 # not a lie
my_height = 172 # cm
my_weight = 71 # kg
my_eyes = 'Brown'
my_teeth = 'White'
my_hair = 'Black'

print "Let's talk about %s." % my_name
print "He's %d centimeters tall." % my_height
print "He's %d kilograms heavy." % my_weight
print "Actually that's not too heavy."
print "He's got %s eyes and %s hair." % (my_eyes, my_hair)
print "His teeth are usually %s depending on the coffee." % my_teeth

# this line is tricky, try to get it exactly right
print "If I add %d, %d, and %d I get %d. I don't know what that means but, whatever." % (
    my_age, my_height, my_weight, my_age + my_height + my_weight)

1)使用第三方库

为了轻松而轻松地执行python脚本, 你可以使用python-shell库实现你的目标。该模块是从Node.js运行Python脚本的简单方法, 它具有基本但高效的进程间通信和更好的错误处理能力。

要在你的项目中安装此模块, 请在节点命令提示符下执行以下命令:

npm install python-shell

Python shell在后台使用子进程来完成此任务。在此处阅读有关此模块API的更多信息, 或访问Github中的存储库。

var myPythonScriptPath = 'script.py';

// Use python shell
var PythonShell = require('python-shell');
var pyshell = new PythonShell(myPythonScriptPath);

pyshell.on('message', function (message) {
    // received a message sent from the Python script (a simple "print" statement)
    console.log(message);
});

// end the input stream and allow the process to exit
pyshell.end(function (err) {
    if (err){
        throw err;
    };

    console.log('finished');
});

在控制台中生成以下结果:

在node.js中执行python脚本并检索输出

请注意, 该脚本假定你已经可以从控制台获得Python作为环境变量。如果你不是这种情况, 请不用担心, Python Shell允许你在执行时设置一些基本选项(即python可执行文件的路径):

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

var options = {
    mode: 'text', pythonPath: 'path/to/python', pythonOptions: ['-u'], scriptPath: 'path/to/my/scripts', args: ['value1', 'value2', 'value3']
};

PythonShell.run('script.py', options, function (err, results) {
    if (err) throw err;
    // results is an array consisting of messages collected during execution
    console.log('results: %j', results);
});

使用参数执行python脚本

一些python脚本需要参数才能执行。 Python Shell允许你在运行脚本时使用options参数添加参数。

以下python脚本(script.py)应在执行时列出所有参数:

import sys

print "\n".join(sys.argv)

例如, 为了在Node.js中执行脚本, 可以通过以下方式直接在控制台中使用python执行脚本:

python script.py "my First Argument" "My Second Argument" --option=123

我们只需要在options对象的args键中提供一个数组作为值, 并带有相应的值:

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

var options = {
    mode: 'text', args: ['my First Argument', 'My Second Argument', '--option=123']
};

PythonShell.run('script.py', options, function (err, results) {
    if (err) throw err;
    // results is an array consisting of messages collected during execution
    console.log('results: %j', results);
});

就是这样! python shell模块使这项任务易于实现, 并且非常全面。

从Node.js向Python提供数据

要将数据从Javascript发送到我们的Python脚本, 我们需要在过程中使用标准输入(stdin)编写文本。

使用python shell, 你可以轻松地处理标准输入并使用send方法发送信息。在此示例中, 我们将发送一个数组(字符串格式), 稍后将使用python处理该数组:

var PythonShell = require('python-shell');
var pyshell = new PythonShell('script.py');

pyshell.send(JSON.stringify([1, 2, 3, 4, 5]));

pyshell.on('message', function (message) {
    // received a message sent from the Python script (a simple "print" statement)
    console.log(message);
});

// end the input stream and allow the process to exit
pyshell.end(function (err) {
    if (err){
        throw err;
    };

    console.log('finished');
});

python脚本应该使用标准输入(stdin)在Javascript提供的数组中打印项目的总和:

import sys, json

#Read data from stdin
def read_in():
    lines = sys.stdin.readlines()
    # Since our input would only be having one line, parse our JSON data from that
    return json.loads(lines[0])

def main():
    #get our data as an array from read_in()
    lines = read_in()

    # Sum  of all the items in the providen array
    total_sum_inArray = 0
    for item in lines:
        total_sum_inArray += item

    #return the sum to the output stream
    print total_sum_inArray

# Start process
if __name__ == '__main__':
    main()

Node.js控制台中的输出应为15。

2)使用内置的child_process模块

如果你不想依靠任何库来完成此任务, 则可以使用child_process生成python环境并自己在该环境上执行脚本。

child_process模块​​提供了以类似于但不相同的方式生成子进程的能力。此功能主要由child_process.spawn函数提供:

// The path to your python script
var myPythonScript = "script.py";
// Provide the path of the python executable, if python is available as environment variable then you can use only "python"
var pythonExecutable = "python.exe";

// Function to convert an Uint8Array to a string
var uint8arrayToString = function(data){
    return String.fromCharCode.apply(null, data);
};

const spawn = require('child_process').spawn;
const scriptExecution = spawn(pythonExecutable, [myPythonScript]);

// Handle normal output
scriptExecution.stdout.on('data', (data) => {
    console.log(uint8arrayToString(data));
});

// Handle error output
scriptExecution.stderr.on('data', (data) => {
    // As said before, convert the Uint8Array to a readable string.
    console.log(uint8arrayToString(data));
});

scriptExecution.on('exit', (code) => {
    console.log("Process quit with code : " + code);
});

在上一个脚本中, 我们已经实现了python-shell模块必须提供的大多数功能。它需要child_process模块​​, 然后我们使用spawn方法以python脚本的路径作为第一个参数来启动python, 并向stdout和stderr属性添加一些侦听器以处理输出。

使用参数执行python脚本

如果你专心, 那么你就会知道我们已经在spawn函数的脚本初始化中使用了参数。 python脚本的路径已经是一个参数, 因此, 如果要添加更多参数, 请随时向spawn函数的第二个参数数组添加更多值:

const scriptExecution = spawn(pythonExecutable, ["my_Script.py", "Argument 1", "Argument 2"]);

从Node.js向Python提供数据

要将数据从Javascript发送到我们的Python脚本, 我们需要在过程中使用标准输入(stdin)编写文本。

在此示例中, 我们将发送一个数组(使用JSON.stringify方法以字符串格式)到Python:

const spawn = require('child_process').spawn;
const scriptExecution = spawn("python.exe", ["script.py"]);

// Handle normal output
scriptExecution.stdout.on('data', (data) => {
    console.log(String.fromCharCode.apply(null, data));
});

// Write data (remember to send only strings or numbers, otherwhise python wont understand)
var data = JSON.stringify([1, 2, 3, 4, 5]);
scriptExecution.stdin.write(data);
// End data write
scriptExecution.stdin.end();

python脚本应该使用标准输入(stdin)在Javascript提供的数组中打印项目的总和:

import sys, json

#Read data from stdin
def read_in():
    lines = sys.stdin.readlines()
    # Since our input would only be having one line, parse our JSON data from that
    return json.loads(lines[0])

def main():
    #get our data as an array from read_in()
    lines = read_in()

    # Sum  of all the items in the providen array
    total_sum_inArray = 0
    for item in lines:
        total_sum_inArray += item

    #return the sum to the output stream
    print total_sum_inArray

# Start process
if __name__ == '__main__':
    main()

Node.js控制台中的输出应为15。

玩得开心 !

来源:

https://www.srcmini02.com/61364.html

微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?