结合 node.js 和 Python

Posted

技术标签:

【中文标题】结合 node.js 和 Python【英文标题】:Combining node.js and Python 【发布时间】:2012-05-27 16:03:52 【问题描述】:

Node.js 与我们的 Web 项目完美匹配,但我们更喜欢 Python 的计算任务很少。我们也已经为他们准备了 Python 代码。 我们非常关心速度,如何以异步非阻塞方式从 node.js 调用 Python “worker”最优雅的方式是什么?

【问题讨论】:

您好,您能和我们分享一下您选择了什么以及效果如何? Python中有一些我们都喜欢使用的库,同时保留了性能和非阻塞选项。谢谢 如何简单地生成/派生一个进程并通过系统 IO 进行通信,就像这个建议:sohamkamani.com/blog/2015/08/21/python-nodejs-comm ? 有一个名为 PyNode 的新桥接库,它允许您调用 Python 并返回 JS 类型。这里演示了thecodinginterface.com/blog/… 对于那些在 Google 上找到此内容的人,请查看 github.com/extremeheat/JSPyBridge,如以下单独答案中所述:***.com/a/68427624/11173996 【参考方案1】:

这听起来像是 zeroMQ 非常适合的场景。这是一个类似于使用 TCP 或 Unix 套接字的消息传递框架,但它更加健壮 (http://zguide.zeromq.org/py:all)

有一个库使用 zeroMQ 来提供运行良好的 RPC 框架。它被称为 zeroRPC (http://www.zerorpc.io/)。这里是你好世界。

Python“Hello x”服务器:

import zerorpc

class HelloRPC(object):
    '''pass the method a name, it replies "Hello name!"'''
    def hello(self, name):
        return "Hello, 0!".format(name)

def main():
    s = zerorpc.Server(HelloRPC())
    s.bind("tcp://*:4242")
    s.run()

if __name__ == "__main__" : main()

还有 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)

【讨论】:

如果有多个客户端会话,zerorpc 能否处理多个状态? 很好的答案,示例,丰富的解释以及我在寻找什么。泰。 +1 如果您像我一样是新手,请安装他们在此处提到的依赖项 - ianhinsdale.com/code/2013/12/08/… 非常感谢! 很好的你好世界演示!下面使用 Rabbitmq 的另一个类似解决方案。 medium.com/@HolmesLaurence/…【参考方案2】:

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

如果您喜欢冒险,请学习 clojure(clojurescript、clojure-py),您将获得与 Java、javascript(包括 node.js)、CLR 和 Python 上的现有代码运行和互操作的相同语言.并且您只需使用 clojure 数据结构即可获得出色的编组协议。

【讨论】:

你知道这样的事情是否适用于 Heroku,它有一个临时文件系统?【参考方案3】:

如果您将 Python 工作者安排在一个单独的进程中(长时间运行的服务器类型进程或按需生成的子进程),您与它的通信将在 node.js 端异步进行。 UNIX/TCP 套接字和标准输入/输出/错误通信在节点中本质上是异步的。

【讨论】:

【参考方案4】:

我使用thoonk.js 和thoonk.py 取得了很大的成功。 Thoonk 利用 Redis(内存中键值存储)为您提供供稿(想想发布/订阅)、队列和作业模式以进行通信。

为什么这比 unix 套接字或直接 tcp 套接字更好?整体性能可能会有所降低,但是 Thoonk 提供了一个非常简单的 API,可以简化手动处理套接字的过程。 Thoonk 还有助于使实现分布式计算模型变得非常简单,该模型允许您扩展 Python 工作线程以提高性能,因为您只需启动 Python 工作线程的新实例并将它们连接到同一个 redis 服务器。

【讨论】:

【参考方案5】:

我也会考虑 Apache Thrift http://thrift.apache.org/

它可以在多种编程语言之间架起桥梁,效率很高,并且支持异步或同步调用。在此处查看完整功能http://thrift.apache.org/docs/features/

多语言对未来计划很有用,例如,如果您以后想用 C++ 完成部分计算任务,使用 Thrift 很容易将其添加到混合中。

【讨论】:

【参考方案6】:

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

这种在 Digg(以及许多其他公司)中大量使用的优势在于,它提供了一种强大、可扩展且稳健的方式,可以让使用任何语言的员工与使用任何语言的客户交谈。

【讨论】:

【参考方案7】:

2019 年更新

有几种方法可以实现这一点,这里是复杂度递增顺序的列表

    Python Shell,您将向 python 控制台写入流,它 会回信给你 Redis Pub Sub,可以有频道 在您的节点 js 发布者推送数据时在 Python 中监听 Websocket 连接,其中 Node 充当客户端,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);
)

destination.py 文件

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 放入其中。不要忘记更改您的 virtualenv 环境

【讨论】:

以上是关于结合 node.js 和 Python的主要内容,如果未能解决你的问题,请参考以下文章

Jade 模板布局不能与 Node.js 结合使用

将 node.js 与本地服务器相结合

websocket与node.js完美结合

将 Azure 自定义视觉模型与 Node.js 结合使用

结合源码分析 Node.js 模块加载与运行原理

node.js + coffeescript + jasmine 的好 IDE [关闭]