Node.js ve Python'u birleştirme


128

Node.js, web projemiz için mükemmel bir eştir, ancak Python'u tercih edeceğimiz birkaç hesaplama görevi vardır. Ayrıca onlar için zaten bir Python kodumuz var. Hız konusunda son derece endişeliyiz, node.js'den bir Python "işçi" olarak eşzamansız, engellemesiz bir şekilde nasıl çağrı yapmanın en zarif yolu nedir?


3
Merhaba, neyi seçtiğinizi ve sizin için nasıl çalıştığını bizimle paylaşır mısınız? Python'da performansı ve engellemeyen seçenekleri korurken kullanmayı sevdiğimiz kütüphaneler var. Teşekkürler
Maziyar 13

Basitçe bir süreci oluşturmak / çatallamak ve bunun önerdiği gibi sistem GÇ'si aracılığıyla iletişim kurmaktan ne haber : sohamkamani.com/blog/2015/08/21/python-nodejs-comm ?
lkahtz

Python'u çağırmanıza ve döndürülen JS türlerini almanıza izin veren PyNode adında yeni bir köprüleme kitaplığı var. Burada gösterilmiştir thecodinginterface.com/blog/…
SciGuyMcQ

Yanıtlar:


86

Node.js ve Python sunucusu arasındaki iletişim için, her iki işlem de aynı sunucuda çalışıyorsa Unix soketlerini ve aksi takdirde TCP / IP soketlerini kullanırdım. Sıralama protokolü için JSON veya protokol tamponu alırdım . İş parçacıklı Python bir darboğaz olarak görünüyorsa, Twisted Python kullanmayı düşünün olarak görünüyorsa, do node.js ile aynı olay odaklı eşzamanlılığı sağlayan düşünün.

Maceracı hissediyorsanız, clojure ( clojurescript , clojure-py ) öğrenin ve Java, JavaScript (node.js dahil), CLR ve Python'daki mevcut kodla çalışan ve birlikte çalışan aynı dili elde edin. Ve sadece clojure veri yapılarını kullanarak mükemmel marşaling protokolü elde edersiniz.


2
Geçici dosya sistemine sahip Heroku'da bunun gibi bir şeyin çalışıp çalışmayacağını biliyor musunuz?
cm2

120

Bu, zeroMQ'nun uygun olacağı bir senaryoya benziyor. TCP veya Unix soketlerini kullanmaya benzer bir mesajlaşma çerçevesidir, ancak çok daha sağlamdır ( http://zguide.zeromq.org/py:all )

Oldukça iyi çalışan bir RPC çerçevesi sağlamak için zeroMQ kullanan bir kitaplık var. SıfırRPC ( http://www.zerorpc.io/ ) olarak adlandırılır . İşte merhaba dünya.

Python "Merhaba x" sunucusu:

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

Ve node.js istemcisi:

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

Veya tam tersi, node.js sunucusu:

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

Ve python istemcisi

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)

4
Zerorpc, birden çok istemci oturumu olması durumunda birden çok durumu işleyebilir mi?
user1027169

İyi cevap, örnek örnekler, bol açıklama ve ne arıyordum. TY. +1
Gaurav Gandhi

1
benim gibi yeniyseniz,
Darpan

Bunun için çok teşekkürler!
Gezim

1
Güzel merhaba dünya demosu! Rabbitmq kullanarak aşağıdaki benzer bir çözüm daha. medium.com/@HolmesLaurence/…
teng

7

Python çalışanınızı ayrı bir işlemde (uzun süre çalışan sunucu tipi işlem veya isteğe bağlı olarak ortaya çıkan bir çocuk) düzenlerseniz, onunla iletişiminiz node.js tarafında eşzamansız olacaktır. UNIX / TCP soketleri ve standart / çıkış / hata iletişimi doğal olarak düğümde eşzamansızdır.


6

Ayrıca Apache Thrift http://thrift.apache.org/

Çeşitli programlama dilleri arasında köprü kurabilir, oldukça verimlidir ve eşzamansız veya senkronizasyon aramaları için destek sağlar. Tüm özelliklere buradan bakın http://thrift.apache.org/docs/features/

Çoklu dil, gelecekteki planlar için yararlı olabilir, örneğin daha sonra hesaplama görevinin bir bölümünü C ++ 'da yapmak isterseniz, Thrift kullanarak bunu karışıma eklemek çok kolaydır.


5

Thoonk.py ile birlikte thoonk.js kullanarak çok başarılı oldum . Thoonk, iletişim için size besleme (düşünün yayınlama / abone olma), kuyruk ve iş modelleri sağlamak için Redis'ten (bellek içi anahtar-değer deposu) yararlanır.

Bu neden unix soketlerinden veya direkt tcp soketlerinden daha iyidir? Genel performans biraz azalabilir, ancak Thoonk bir soket ile manuel olarak uğraşmayı basitleştiren gerçekten basit bir API sağlar. Thoonk ayrıca, python çalışanlarınızın yeni örneklerini çalıştırdığınız ve onları aynı redis sunucusuna bağladığınızdan, python çalışanlarınızı performansı artırmak için ölçeklendirmenize olanak tanıyan dağıtılmış bir bilgi işlem modeli uygulamanın gerçekten önemsiz olmasına yardımcı olur.


3

Örneğin, size arka plan işlerini göndermek için harika bir yol sağlayacak ve işlendikten sonra sonuçlarını eşzamansız olarak alacak mükemmel Gearman kullanarak bazı iş kuyruğu kullanmanızı öneririm .

Digg'de (diğerleri arasında) yoğun olarak kullanılan bunun avantajı, çalışanların herhangi bir dilde müşterilerle herhangi bir dilde konuşmasını sağlamak için güçlü, ölçeklenebilir ve sağlam bir yol sağlamasıdır.


1

2019 Güncellemesi

Bunu başarmanın birkaç yolu var ve işte artan karmaşıklık sırasındaki liste.

  1. Python Shell, python konsoluna akışlar yazacaksın ve o sana geri yazacak
  2. Redis Pub Sub, düğüm js yayıncınız verileri aktarırken Python'da dinleyen bir kanalınız olabilir
  3. Node'un istemci, Python'un sunucu olarak davrandığı veya tersinin olduğu Websocket bağlantısı
  4. Express / Flask / Tornado vb. İle API bağlantısı, diğerinin sorgulaması için açığa çıkan bir API uç noktasıyla ayrı ayrı çalışır

Yaklaşım 1 Python Kabuğu En basit yaklaşım

source.js dosyası

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

hedef.py dosyası

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

Notlar : Subscriber adında, source.js dosyasıyla aynı seviyede olan bir klasör oluşturun ve içine hedef.py'yi koyun. Virtualenv ortamınızı değiştirmeyi unutmayın

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.