如何从 Node.js 调用 Python 函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23450534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 02:59:33  来源:igfitidea点击:

How to call a Python function from Node.js

pythonnode.jsexpress

提问by Genjuro

I have an Express Node.js application, but I also have a machine learning algorithm to use in Python. Is there a way I can call Python functions from my Node.js application to make use of the power of machine learning libraries?

我有一个 Express Node.js 应用程序,但我也有一个在 Python 中使用的机器学习算法。有没有一种方法可以从我的 Node.js 应用程序调用 Python 函数来利用机器学习库的强大功能?

回答by NeverForgetY2K

Easiest way I know of is to use "child_process" package which comes packaged with node.

我所知道的最简单的方法是使用 node.js 打包的“child_process”包。

Then you can do something like:

然后你可以做这样的事情:

const spawn = require("child_process").spawn;
const pythonProcess = spawn('python',["path/to/script.py", arg1, arg2, ...]);

Then all you have to do is make sure that you import sysin your python script, and then you can access arg1using sys.argv[1], arg2using sys.argv[2], and so on.

然后你所要做的就是确保你import sys在你的 python 脚本中,然后你可以访问arg1using sys.argv[1]arg2using sys.argv[2],等等。

To send data back to node just do the following in the python script:

要将数据发送回节点,只需在 python 脚本中执行以下操作:

print(dataToSendBack)
sys.stdout.flush()

And then node can listen for data using:

然后节点可以使用以下方法侦听数据:

pythonProcess.stdout.on('data', (data) => {
    // Do something with the data returned from python script
});

Since this allows multiple arguments to be passed to a script using spawn, you can restructure a python script so that one of the arguments decides which function to call, and the other argument gets passed to that function, etc.

由于这允许使用 spawn 将多个参数传递给脚本,因此您可以重构 python 脚本,以便其中一个参数决定调用哪个函数,另一个参数传递给该函数,等等。

Hope this was clear. Let me know if something needs clarification.

希望这很清楚。如果有什么需要澄清的,请告诉我。

回答by Amit Upadhyay

Examplefor people who are from Python background and want to integrate their machine learning model in the Node.js application:

对于具有 Python 背景并希望将他们的机器学习模型集成到 Node.js 应用程序的人员的示例

It uses the child_processcore module:

它使用child_process核心模块:

const express = require('express')
const app = express()

app.get('/', (req, res) => {

    const { spawn } = require('child_process');
    const pyProg = spawn('python', ['./../pypy.py']);

    pyProg.stdout.on('data', function(data) {

        console.log(data.toString());
        res.write(data);
        res.end('end');
    });
})

app.listen(4000, () => console.log('Application listening on port 4000!'))

It doesn't require sysmodule in your Python script.

它不需要sys您的 Python 脚本中的模块。

Below is a more modular way of performing the task using Promise:

以下是使用以下命令执行任务的更模块化的方式Promise

const express = require('express')
const app = express()

let runPy = new Promise(function(success, nosuccess) {

    const { spawn } = require('child_process');
    const pyprog = spawn('python', ['./../pypy.py']);

    pyprog.stdout.on('data', function(data) {

        success(data);
    });

    pyprog.stderr.on('data', (data) => {

        nosuccess(data);
    });
});

app.get('/', (req, res) => {

    res.write('welcome\n');

    runPy.then(function(fromRunpy) {
        console.log(fromRunpy.toString());
        res.end(fromRunpy);
    });
})

app.listen(4000, () => console.log('Application listening on port 4000!'))

回答by Soumik Rakshit

The python-shellmodule by extrabaconis a simple way to run Python scripts from Node.js with basic, but efficient inter-process communication and better error handling.

python-shell通过模块extrabacon是一个简单的方法来基本运行Node.js的从Python脚本,但高效的进程间通信和更好的错误处理。

Installation:npm install python-shell.

安装:npm install python-shell

Running a simple Python script:

运行一个简单的 Python 脚本:

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

PythonShell.run('my_script.py', function (err) {
  if (err) throw err;
  console.log('finished');
});

Running a Python script with arguments and options:

运行带有参数和选项的 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('my_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);
});

For the full documentation and source code, check out https://github.com/extrabacon/python-shell

有关完整的文档和源代码,请查看https://github.com/extrabacon/python-shell

回答by 1mike12

I'm on node 10 and child process 1.0.2. The data from python is a byte array and has to be converted. Just another quick example of making a http request in python.

我在 node 10 和 child process 上1.0.2。来自python的数据是一个字节数组,必须进行转换。这是在 python 中发出 http 请求的另一个快速示例。

node

节点

const process = spawn("python", ["services/request.py", "https://www.google.com"])

return new Promise((resolve, reject) =>{
    process.stdout.on("data", data =>{
        resolve(data.toString()); // <------------ by default converts to utf-8
    })
    process.stderr.on("data", reject)
})

request.py

请求文件

import urllib.request
import sys

def karl_morrison_is_a_pedant():   
    response = urllib.request.urlopen(sys.argv[1])
    html = response.read()
    print(html)
    sys.stdout.flush()

karl_morrison_is_a_pedant()

p.s. not a contrived example since node's http module doesn't load a few requests I need to make

ps 不是一个人为的例子,因为节点的 http 模块没有加载我需要发出的一些请求

回答by Jonathan

You could take your python, transpileit, and then call it as if it were javascript. I have done this succesfully for screeps and even got it to run in the browser a la brython.

你可以使用你的python,对其进行转译,然后像调用javascript一样调用它。我已经成功地为 screeps 做到了这一点,甚至让它在浏览器中运行 a la brython

回答by bormat

Most of previous answers call the success of the promise in the on("data"), it is not the proper way to do it because if you receive a lot of data you will only get the first part. Instead you have to do it on the end event.

以前的大多数答案都将 on("data") 中的承诺称为成功,这不是正确的做法,因为如果您收到大量数据,您将只能获得第一部分。相反,您必须在结束事件中执行此操作。

const { spawn } = require('child_process');
const pythonDir = (__dirname + "/../pythonCode/"); // Path of python script folder
const python = pythonDir + "pythonEnv/bin/python"; // Path of the Python interpreter

/** remove warning that you don't care about */
function cleanWarning(error) {
    return error.replace(/Detector is not able to detect the language reliably.\n/g,"");
}

function callPython(scriptName, args) {
    return new Promise(function(success, reject) {
        const script = pythonDir + scriptName;
        const pyArgs = [script, JSON.stringify(args) ]
        const pyprog = spawn(python, pyArgs );
        let result = "";
        let resultError = "";
        pyprog.stdout.on('data', function(data) {
            result += data.toString();
        });

        pyprog.stderr.on('data', (data) => {
            resultError += cleanWarning(data.toString());
        });

        pyprog.stdout.on("end", function(){
            if(resultError == "") {
                success(JSON.parse(result));
            }else{
                console.error(`Python error, you can reproduce the error with: \n${python} ${script} ${pyArgs.join(" ")}`);
                const error = new Error(resultError);
                console.error(error);
                reject(resultError);
            }
        })
   });
}
module.exports.callPython = callPython;

Call:

称呼:

const pythonCaller = require("../core/pythonCaller");
const result = await pythonCaller.callPython("preprocessorSentiment.py", {"thekeyYouwant": value});

python:

Python:

try:
    argu = json.loads(sys.argv[1])
except:
    raise Exception("error while loading argument")

回答by Geordie

You can now use RPC libraries that support Python and Javascript such as zerorpc

您现在可以使用支持 Python 和 Javascript 的 RPC 库,例如zerorpc

From their front page:

从他们的首页:

Node.js Client

Node.js 客户端

var zerorpc = require("zerorpc");

var client = new zerorpc.Client();
client.connect("tcp://127.0.0.1:4242");

client.invoke("hello", "RPC", function(error, res, more) {
    console.log(res);
});

Python Server

蟒蛇服务器

import zerorpc

class HelloRPC(object):
    def hello(self, name):
        return "Hello, %s" % name

s = zerorpc.Server(HelloRPC())
s.bind("tcp://0.0.0.0:4242")
s.run()