Node.js से पायथन फ़ंक्शन कैसे कॉल करें


208

मेरे पास एक एक्सप्रेस Node.js अनुप्रयोग है, लेकिन मेरे पास पायथन में उपयोग करने के लिए एक मशीन लर्निंग एल्गोरिदम भी है। क्या मशीन सीखने की लाइब्रेरी की शक्ति का उपयोग करने के लिए मैं अपने Node.js एप्लिकेशन से पायथन कार्यों को कॉल कर सकता हूं?


4
नोड-पायथन । हालांकि इसका इस्तेमाल खुद कभी नहीं किया।
यूनीवरियो

22
दो साल बाद, node-pythonएक परित्यक्त परियोजना लगती है।
imrek


अजगर को संकलन के लिए जावास्क्रिप्ट में github.com/QQuick/Transcrypt भी देखें और फिर इसे लागू करें
जोनाथन

जवाबों:


262

सबसे आसान तरीका मुझे पता है कि "child_process" पैकेज का उपयोग करना है जो नोड के साथ पैक किया गया है।

तब आप कुछ ऐसा कर सकते हैं:

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

फिर आपको बस इतना करना है कि आप import sysअपने अजगर स्क्रिप्ट में सुनिश्चित करें , और तब आप का उपयोग arg1कर sys.argv[1], arg2का उपयोग कर सकते हैंsys.argv[2] , और इसी तरह।

नोड में डेटा वापस भेजने के लिए सिर्फ पायथन लिपि में निम्न कार्य करें:

print(dataToSendBack)
sys.stdout.flush()

और फिर नोड डेटा का उपयोग करके सुन सकता है:

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

चूँकि यह स्पॉन का उपयोग करके एक स्क्रिप्ट में कई तर्कों को पारित करने की अनुमति देता है, आप एक पायथन लिपि का पुनर्गठन कर सकते हैं ताकि एक तर्क यह तय करे कि किस फ़ंक्शन को कॉल करना है, और दूसरा तर्क उस फ़ंक्शन को पास हो जाता है, आदि।

आशा है कि यह स्पष्ट था। अगर कुछ स्पष्टीकरण की जरूरत है तो मुझे बताएं।


17
@ PauloS.Abreu: मेरे पास जो समस्या execहै, वह यह है कि यह एक स्ट्रीम के बजाय एक बफर लौटाता है, और यदि आपका डेटा maxBufferसेटिंग से अधिक हो जाता है, जो कि 200kB तक चूक जाता है, तो आपको एक बफर पार हो जाता है और आपकी प्रक्रिया मार जाती है। चूंकि spawnयह धाराओं का उपयोग करता है, इसलिए यह अधिक लचीला है exec
NeverForgetY2K

2
बस एक छोटा सा नोट, यदि आप नोड का उपयोग करते हैं, तो आपको शायद प्रक्रिया कीवर्ड का उपयोग नहीं करना चाहिए
alexvicegrab

2
मुझे बाहरी पाइप निर्भरता कैसे स्थापित करनी चाहिए? मुझे किसी प्रोजेक्ट के लिए सुन्न की जरूरत है और वह इसे नहीं चला सकता क्योंकि इसमें यह स्थापित नहीं है।
javiergarval

2
@javiergarval टिप्पणी के बजाय एक नए प्रश्न के रूप में बेहतर होगा।
NeverForgetY2K

3
क्या प्रिंट के अलावा अजगर से डेटा वापस करने का कोई और तरीका है? मेरी पाइथन लिपि बहुत सारे लॉग डेटा का उत्पादन करती है और जाहिर तौर पर यह सभी डेटा को फ्लश करने में परेशानी होती है
lxknvlk

111

ऐसे लोगों के लिए उदाहरण जो पायथन पृष्ठभूमि से हैं और अपने मशीन लर्निंग मॉडल को Node.js एप्लिकेशन में एकीकृत करना चाहते हैं:

यह 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!'))

इसे sysआपके पाइथन लिपि में मॉड्यूल की आवश्यकता नहीं है ।

नीचे कार्य का उपयोग करने का एक अधिक मॉड्यूलर तरीका है 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!'))

8
मुझे आश्चर्य है कि यह अधिक वोट नहीं मिला है। जबकि @ NeverForgetY2K का उत्तर ठीक है, इस उत्तर में पोर्ट को सुनने सहित एक अधिक विस्तृत उदाहरण है, और अच्छी तरह से कॉन्स्ट एंड वादों जैसे अधिक आधुनिक जेएस सम्मेलनों का उपयोग करता है।
माइक विलियमसन

2
महान उदाहरण है। वादा एक अच्छा कुछ त्रुटियों का पता लगाने के लिए मैं अजगर स्क्रिप्ट पर था।
htafoya

38

python-shellमॉड्यूल द्वारा extrabaconबुनियादी साथ Node.js से पाइथन स्क्रिप्ट को चलाने के लिए एक आसान तरीका है, लेकिन कुशल अंतर संचार प्रक्रिया और बेहतर त्रुटि हैंडलिंग।

स्थापना: npm install python-shell

एक साधारण पायथन स्क्रिप्ट चलाना:

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

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

तर्क और विकल्पों के साथ पायथन स्क्रिप्ट चलाना:

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

पूर्ण प्रलेखन और स्रोत कोड के लिए, https://github.com/extrabacon/python-shell देखें


3
यह समस्या मुझे इसके उपयोग से रोक रही है - github.com/extrabacon/python-shell/issues/179
mhlavacka

1
यदि आपको यह त्रुटि मिल रही है - TypeError: PythonShell.run कोई फ़ंक्शन नहीं है, तो सुनिश्चित करें कि आप इसे इस तरह आयात करते हैं {PythonShell} = आवश्यकता ('पायथन-शेल');
मोहम्मद

4

अब आप 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);
});

पायथन सर्वर

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

आप Node और Python दोनों तरफ socket.io का भी उपयोग कर सकते हैं ।
ब्रूनो गाबुज़ोमू

3

पिछले उत्तरों में से अधिकांश वादे की सफलता को ("डेटा") कहते हैं, यह ऐसा करने का उचित तरीका नहीं है क्योंकि यदि आप बहुत अधिक डेटा प्राप्त करते हैं तो आपको केवल पहला भाग ही मिलेगा। इसके बजाय आपको इसे अंतिम ईवेंट पर करना होगा।

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;

कॉल करें:

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

अजगर:

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

2

मैं नोड 10 और चाइल्ड प्रोसेस पर हूं 1.0.2। अजगर से डेटा एक बाइट सरणी है और इसे परिवर्तित करना होगा। अजगर में http अनुरोध करने का सिर्फ एक और त्वरित उदाहरण।

नोड

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

क्योंकि नोड के http मॉड्यूल से कुछ अनुरोधों को लोड नहीं किया जाता है जो मुझे करने की आवश्यकता नहीं है


मेरे पास नोडज पर सर्वर बैकएंड बिल्ड है और मेरे पास कुछ मशीन लर्निंग संबंधित पाइथन स्क्रिप्ट्स हैं जो मैं अपने नोडज सर्वर पर अनुरोध को प्राप्त करने के बाद नोड्ज के माध्यम से चाइल्ड प्रोसेस स्पॉन का उपयोग करके स्पॉन करता हूं। जैसा कि इस धागे में सुझाया गया है। मेरा प्रश्न यह है कि क्या यह करने का सही तरीका है या मैं अपने अजगर की स्क्रिप्ट को एक फ्लास्क सेवा की तरह चला सकता हूं, जो zmq का उपयोग करते हुए एक पोर्ट से बंधी है और इस सेवा के लिए नोडज से एक वादा चलाती है। सही से मेरा मतलब है कि मेमोरी सेविंग और स्पीड सेविंग मेथड कौन सा है?
असविन

1
आप शायद स्वतंत्र रूप से चल रहे अजगर सामान चाहते हैं। आप हार्ड कोड निर्भरता नहीं चाहते हैं, विशेष रूप से कुछ और अधिक के लिए एक एमएल सेवा के रूप में जटिल। क्या होगा यदि आप इस वास्तुकला में एक और टुकड़ा जोड़ना चाहते हैं? मिलीलीटर के सामने एक कैशिंग परत की तरह, या एमएल मॉडल में अतिरिक्त मापदंडों को जोड़ने का एक तरीका है? यह अजगर सर्वर को चलाने के लिए मेमोरी है, लेकिन आपको संभवतः लचीलेपन की आवश्यकता होगी। बाद में आप दो टुकड़ों को दो सर्वरों में अलग कर सकते हैं
१ike

उन्होंने पूछा कि क्या वह किसी समारोह को बुला सकते हैं , इस सवाल का जवाब नहीं है।
के - एसओ में विषाक्तता बढ़ रही है।

2
@ 1mike12 "karl_morrison_is_a_pedant ()" haha ​​love it mate!
के - एसओ में विषाक्तता बढ़ रही है।

0

आप अपने अजगर को ले जा सकते हैं, उसे स्थानांतरित कर सकते हैं, और फिर इसे ऐसे कह सकते हैं जैसे कि यह जावास्क्रिप्ट हो। मैंने यह पूरी तरह से स्क्रैप के लिए किया है और यहां तक ​​कि इसे ब्राउज़र में एक ला ब्रीथोन चलाने के लिए मिला है ।


0
/*eslint-env es6*/
/*global require*/
/*global console*/
var express = require('express'); 
var app = express();

// Creates a server which runs on port 3000 and  
// can be accessed through localhost:3000
app.listen(3000, function() { 
    console.log('server running on port 3000'); 
} ) 

app.get('/name', function(req, res) {

    console.log('Running');

    // Use child_process.spawn method from  
    // child_process module and assign it 
    // to variable spawn 
    var spawn = require("child_process").spawn;   
    // Parameters passed in spawn - 
    // 1. type_of_script 
    // 2. list containing Path of the script 
    //    and arguments for the script  

    // E.g : http://localhost:3000/name?firstname=Levente
    var process = spawn('python',['apiTest.py', 
                        req.query.firstname]);

    // Takes stdout data from script which executed 
    // with arguments and send this data to res object
    var output = '';
    process.stdout.on('data', function(data) {

        console.log("Sending Info")
        res.end(data.toString('utf8'));
    });

    console.log(output);
}); 

इसने मेरे लिए काम किया। इस कोड स्निपेट के लिए आपका python.exe आपको पथ चर में जोड़ा जाना चाहिए। इसके अलावा, सुनिश्चित करें कि आपकी अजगर स्क्रिप्ट आपके प्रोजेक्ट फ़ोल्डर में है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.