结合node.js和Python

结合node.js和Python,python,node.js,ipc,Python,Node.js,Ipc,js非常适合我们的web项目,但是很少有我们更喜欢Python的计算任务。我们也已经为它们编写了Python代码。 我们非常关注速度,如何以异步非阻塞方式从node.js调用Python“worker”最优雅的方式是什么?如果您安排将Python worker放在单独的进程中(长时间运行的服务器类型进程或按需生成的子进程),在node.js端,您与它的通信将是异步的。UNIX/TCP套接字和stdin/out/err通信在节点中本质上是异步的。对于node.js和Python服务器之间的通信,如

js非常适合我们的web项目,但是很少有我们更喜欢Python的计算任务。我们也已经为它们编写了Python代码。
我们非常关注速度,如何以异步非阻塞方式从node.js调用Python“worker”最优雅的方式是什么?

如果您安排将Python worker放在单独的进程中(长时间运行的服务器类型进程或按需生成的子进程),在node.js端,您与它的通信将是异步的。UNIX/TCP套接字和stdin/out/err通信在节点中本质上是异步的。

对于node.js和Python服务器之间的通信,如果两个进程运行在同一台服务器上,我将使用UNIX套接字,否则使用TCP/IP套接字。对于封送协议,我将使用JSON或。如果线程Python显示为瓶颈,请考虑使用 提供与do node.js相同的事件驱动并发性


如果你觉得有冒险精神,学习(,)你将获得与Java、JavaScript(包括node.js)、CLR和Python上的现有代码运行和互操作相同的语言。通过简单地使用clojure数据结构,您就可以获得极好的编组协议。

我建议使用一些工作队列,例如使用优秀的,这将为您提供一种很好的方法来调度后台作业,并在处理完作业后异步获得结果


Digg(以及其他许多公司)大量使用的这种方法的优点是,它提供了一种强大、可扩展和健壮的方法,使任何语言的员工能够用任何语言与客户交谈。

我已经在使用中取得了很多成功。Thoonk利用Redis(内存键值存储)为您提供用于通信的提要(思考发布/订阅)、队列和作业模式


为什么这比unix套接字或直接tcp套接字更好?总体性能可能会降低一些,但是Thoonk提供了一个非常简单的API,简化了手动处理套接字的过程。THOONK也有助于实现一个分布式计算模型,这使得您可以扩展Python的工作人员来提高性能,这是非常微不足道的,因为您只需将Python工作人员的新实例旋转并连接到同一个ReDIS服务器。

< P>我也会考虑Apache节省/

它可以在多种编程语言之间架起桥梁,效率很高,并且支持异步或同步调用。请参见此处的全部功能


多语言对将来的计划可能有用,例如,如果以后你想在C++中完成部分计算任务,那么很容易使用节约来把它添加到混合中。

< P>这听起来是一个不错的例子。它是一个消息传递框架,类似于使用TCP或Unix套接字,但更健壮()

有一个库使用zeroMQ提供一个运行良好的RPC框架。它被称为zeroRPC()。这是你好世界

Python“Hello x”服务器:

以及node.js客户端:

var zerorpc = require("zerorpc");

var client = new zerorpc.Client();
client.connect("tcp://127.0.0.1:4242");
//calls the method on the python object
client.invoke("hello", "World", function(error, reply, streaming) {
    if(error){
        console.log("ERROR: ", error);
    }
    console.log(reply);
});
反之亦然,node.js服务器:

var zerorpc = require("zerorpc");

var server = new zerorpc.Server({
    hello: function(name, reply) {
        reply(null, "Hello, " + name, false);
    }
});

server.bind("tcp://0.0.0.0:4242");
还有python客户端

import zerorpc, sys

c = zerorpc.Client()
c.connect("tcp://127.0.0.1:4242")
name = sys.argv[1] if len(sys.argv) > 1 else "dude"
print c.hello(name)

2019年更新

有几种方法可以实现这一点,下面是按复杂性的增加顺序列出的列表

  • pythonshell,您将向Python控制台写入流,然后 我会给你回信的
  • Redis酒吧,你可以有一个频道 在节点js publisher推送数据时侦听Python
  • Websocket连接,其中节点充当客户端,Python充当 作为服务器,反之亦然
  • 与Express/Flask/Tornado等单独工作的API连接,API端点暴露给另一方查询
  • 方法1 Python Shell最简单的方法

    source.js文件

    const ps = require('python-shell')
    // very important to add -u option since our python script runs infinitely
    var options = {
        pythonPath: '/Users/zup/.local/share/virtualenvs/python_shell_test-TJN5lQez/bin/python',
        pythonOptions: ['-u'], // get print results in real-time
        // make sure you use an absolute path for scriptPath
        scriptPath: "./subscriber/",
        // args: ['value1', 'value2', 'value3'],
        mode: 'json'
    };
    
    const shell = new ps.PythonShell("destination.py", options);
    
    function generateArray() {
        const list = []
        for (let i = 0; i < 1000; i++) {
            list.push(Math.random() * 1000)
        }
        return list
    }
    
    setInterval(() => {
        shell.send(generateArray())
    }, 1000);
    
    shell.on("message", message => {
        console.log(message);
    })
    
    import datetime
    import sys
    import time
    import numpy
    import talib
    import timeit
    import json
    import logging
    logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
    
    size = 1000
    p = 100
    o = numpy.random.random(size)
    h = numpy.random.random(size)
    l = numpy.random.random(size)
    c = numpy.random.random(size)
    v = numpy.random.random(size)
    
    def get_indicators(values):
        # Return the RSI of the values sent from node.js
        numpy_values = numpy.array(values, dtype=numpy.double) 
        return talib.func.RSI(numpy_values, 14)
    
    for line in sys.stdin:
        l = json.loads(line)
        print(get_indicators(l))
        # Without this step the output may not be immediately available in node
        sys.stdout.flush()
    

    注意事项:创建一个名为subscriber的文件夹,该文件夹与source.js文件处于同一级别,并将destination.py放入其中。别忘了更改您的VirtualEnvironment

    您知道这样的东西是否能在Heroku上工作吗?Heroku有一个短暂的文件系统。您好,您能和我们分享一下您选择了什么以及它是如何为您工作的吗?Python中有一些我们都喜欢使用的库,同时保留了性能和非阻塞选项。感谢您简单地生成/分叉一个进程并通过系统IO进行通信,如下面的建议:?有一个名为PyNode的新桥接库,允许您调用Python并返回JS类型。这里演示了zerorpc在有多个客户端会话的情况下可以处理多个状态吗?很好的答案、示例、丰富的解释以及我在寻找什么。泰+1如果您是像我一样的新手,请按照此处提到的方式安装依赖项-非常感谢!你好,世界演示!下面使用Rabbitmq的另一个类似解决方案。
    import datetime
    import sys
    import time
    import numpy
    import talib
    import timeit
    import json
    import logging
    logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
    
    size = 1000
    p = 100
    o = numpy.random.random(size)
    h = numpy.random.random(size)
    l = numpy.random.random(size)
    c = numpy.random.random(size)
    v = numpy.random.random(size)
    
    def get_indicators(values):
        # Return the RSI of the values sent from node.js
        numpy_values = numpy.array(values, dtype=numpy.double) 
        return talib.func.RSI(numpy_values, 14)
    
    for line in sys.stdin:
        l = json.loads(line)
        print(get_indicators(l))
        # Without this step the output may not be immediately available in node
        sys.stdout.flush()