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


当前回答

你可以在NPM上查看我的套餐 https://www.npmjs.com/package/@guydev/native-python

它提供了一种非常简单而强大的方式来从node运行python函数

import { runFunction } from '@guydev/native-python'

const example = async () => {
   const input = [1,[1,2,3],{'foo':'bar'}]
   const { error, data } = await runFunction('/path/to/file.py','hello_world', '/path/to/python', input)

   // error will be null if no error occured.
   if (error) {
       console.log('Error: ', error)
   }

   else {
       console.log('Success: ', data)
       // prints data or null if function has no return value
   }
}

python模块

# module: file.py

def hello_world(a,b,c):
    print( type(a), a) 
    # <class 'int'>, 1

    print(type(b),b)
    # <class 'list'>, [1,2,3]

    print(type(c),c)
    # <class 'dict'>, {'foo':'bar'}

其他回答

Boa很适合您的需求,请参阅扩展Python tensorflow keras的示例。JavaScript中的顺序类。

const fs = require('fs');
const boa = require('@pipcook/boa');
const { tuple, enumerate } = boa.builtins();

const tf = boa.import('tensorflow');
const tfds = boa.import('tensorflow_datasets');

const { keras } = tf;
const { layers } = keras;

const [
  [ train_data, test_data ],
  info
] = tfds.load('imdb_reviews/subwords8k', boa.kwargs({
  split: tuple([ tfds.Split.TRAIN, tfds.Split.TEST ]),
  with_info: true,
  as_supervised: true
}));

const encoder = info.features['text'].encoder;
const padded_shapes = tuple([
  [ null ], tuple([])
]);
const train_batches = train_data.shuffle(1000)
  .padded_batch(10, boa.kwargs({ padded_shapes }));
const test_batches = test_data.shuffle(1000)
  .padded_batch(10, boa.kwargs({ padded_shapes }));

const embedding_dim = 16;
const model = keras.Sequential([
  layers.Embedding(encoder.vocab_size, embedding_dim),
  layers.GlobalAveragePooling1D(),
  layers.Dense(16, boa.kwargs({ activation: 'relu' })),
  layers.Dense(1, boa.kwargs({ activation: 'sigmoid' }))
]);

model.summary();
model.compile(boa.kwargs({
  optimizer: 'adam',
  loss: 'binary_crossentropy',
  metrics: [ 'accuracy' ]
}));

完整的示例在:https://github.com/alibaba/pipcook/blob/master/example/boa/tf2/word-embedding.js

我在另一个项目pipook中使用了Boa,这是为了解决JavaScript开发人员的机器学习问题,我们通过Boa库在Python生态系统(tensorflow,keras,pytorch)上实现了ML/DL模型。

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

安装:

npm: NPM安装python-shell。

或者用纱线: 纱线加蟒壳

运行一个简单的Python脚本:

const PythonShell = require('python-shell').PythonShell;

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

运行带有参数和选项的Python脚本:

const PythonShell = require('python-shell').PythonShell;

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

要获得完整的文档和源代码,请访问https://github.com/extrabacon/python-shell

const util = require('util');
const exec = util.promisify(require('child_process').exec);
    
function runPythonFile() {
  const { stdout, stderr } = await exec('py ./path_to_python_file -s asdf -d pqrs');
  if (stdout) { // do something }
  if (stderr) { // do something }
}

欲了解更多信息,请访问Nodejs官方子进程页面:https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback

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

从他们的头版:

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服务器

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

许多例子都是过时的,并且涉及复杂的设置。您可以尝试JSPyBridge/pythonia(完全披露:我是作者)。它是一种普通的JS,可以让你操作外部Python对象,就好像它们存在于JS中一样。事实上,它实现了互操作性,因此Python代码可以通过回调和传递函数返回调用JS。

numpy + matplotlib的例子,用ES6导入系统:

import { py, python } from 'pythonia'
const np = await python('numpy')
const plot = await python('matplotlib.pyplot')

// Fixing random state for reproducibility
await np.random.seed(19680801)
const [mu, sigma] = [100, 15]
// Inline expression evaluation for operator overloading
const x = await py`${mu} + ${sigma} * ${np.random.randn(10000)}`

// the histogram of the data
const [n, bins, patches] = await plot.hist$(x, 50, { density: true, facecolor: 'g', alpha: 0.75 })
console.log('Distribution', await n) // Always await for all Python access
await plot.show()
python.exit()

通过CommonJS(没有顶级await):

const { py, python } = require('pythonia')
async function main() {
  const np = await python('numpy')
  const plot = await python('matplotlib.pyplot')
  ...
  // the rest of the code
}
main().then(() => python.exit()) // If you don't call this, the process won't quit by itself.