Nodejs là một nền tảng phát triển web phổ biến hiện nay vì những lợi ích và sự tiện lợi mà nó đem lại. Nhưng có một vài điều mà nó còn chưa hỗ trợ như machine learning, deep learning và các thư viện về trí tuệ nhân tạo.Thật may Python hỗ trợ tất cả những thứ này và đôi khi là còn nhiều thứ khác mà nodejs không có. Mọi người sẽ tự hỏi là tại sao không sử dụng Django Framework của python để dựng những ứng dụng web có thể tích hợp machine learning và trí tuệ nhân tạo. Điều này có vẻ ổn đấy nếu khi ta dựng ứng dụng đó từ đầu. Nhưng nếu ứng dụng của chúng ta là Nodejs và nó đang chạy nhưng giờ ta lại muốn thêm machine learning vào thì sao. Không sao ta vẫn có thể kết nối Nodejs và Python như thường, bằng cách sử dụng child process module for Nodejs
.
Chúng ta sẽ có 3 cách để tương tác giữa python và nodejs nhưng trước tiên ta cần setup đã
Setup
- Tạo một project Express đơn giản:1234npm ini -ynpm i express nodemon --save
Tạo fileserver.js
đơn giản123456789<span class="token comment">// Server.js</span><span class="token keyword">var</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span>‘express’<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">var</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>‘server running on port <span class="token number">3000</span>’<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
Trong filepackage.json
1234567891011121314151617181920<span class="token comment">// package.json</span><span class="token punctuation">{</span><span class="token string">"name"</span><span class="token punctuation">:</span> <span class="token string">"node_integrate_python"</span><span class="token punctuation">,</span><span class="token string">"version"</span><span class="token punctuation">:</span> <span class="token string">"1.0.0"</span><span class="token punctuation">,</span><span class="token string">"description"</span><span class="token punctuation">:</span> <span class="token string">""</span><span class="token punctuation">,</span><span class="token string">"main"</span><span class="token punctuation">:</span> <span class="token string">"index.js"</span><span class="token punctuation">,</span><span class="token string">"scripts"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token string">"start"</span><span class="token punctuation">:</span> <span class="token string">"nodemon server.js"</span><span class="token punctuation">,</span><span class="token string">"test"</span><span class="token punctuation">:</span> <span class="token string">"echo "Error: no test specified" && exit 1"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string">"keywords"</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string">"author"</span><span class="token punctuation">:</span> <span class="token string">""</span><span class="token punctuation">,</span><span class="token string">"license"</span><span class="token punctuation">:</span> <span class="token string">"ISC"</span><span class="token punctuation">,</span><span class="token string">"dependencies"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token string">"express"</span><span class="token punctuation">:</span> <span class="token string">"^4.17.1"</span><span class="token punctuation">,</span><span class="token string">"nodemon"</span><span class="token punctuation">:</span> <span class="token string">"^2.0.2"</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
Hãy thử chạy project trước khi tiếp tục12npm start
Kết quả như sau là được1234567[nodemon] 2.0.2[nodemon] to restart at any time, enter `rs`[nodemon] watching dir(s): *.*[nodemon] watching extensions: js,mjs,json[nodemon] starting `node server.js`server running on port 3000
Tiếp đến ta cần một file chưa script xử lý pythonprocess.py
:123456<span class="token keyword">import</span> sys<span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"Output from Python"</span><span class="token punctuation">)</span><span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"First name: "</span> <span class="token operator">+</span> sys<span class="token punctuation">.</span>argv<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"Last name: "</span> <span class="token operator">+</span> sys<span class="token punctuation">.</span>argv<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
Cách 1: gọi Python script từ Node child process
- Chúng ta cần sửa lại một chút file server của Express để nó gọi đến Python script child process123456789101112131415161718192021<span class="token comment">// server.js</span><span class="token operator">...</span>app<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'/name'</span><span class="token punctuation">,</span> callName<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">function</span> <span class="token function">callName</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> res<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">var</span> spawn <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'child_process'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>spawn<span class="token punctuation">;</span><span class="token comment">// E.g : http://localhost:3000/name?firstname=van&lastname=nghia</span><span class="token keyword">var</span> process <span class="token operator">=</span> <span class="token function">spawn</span><span class="token punctuation">(</span><span class="token string">'python'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'./process.py'</span><span class="token punctuation">,</span>req<span class="token punctuation">.</span>query<span class="token punctuation">.</span>firstname<span class="token punctuation">,</span>req<span class="token punctuation">.</span>query<span class="token punctuation">.</span>lastname<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>process<span class="token punctuation">.</span>stdout<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'data'</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span> <span class="token punctuation">{</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>data<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>data<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span>
Hàm được sử dụng để tương tác giữa nodejs và python ở đây là child_process.spawn()
theo như định nghĩa thì :12child_process.spawn(): This method helps us to spawn child process asynchronously.
hàmchild_process.spawn()
sẽ có các tham số như sau12345<span class="token keyword">var</span> process <span class="token operator">=</span> <span class="token function">spawn</span><span class="token punctuation">(</span><span class="token string">'python'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'./process.py'</span><span class="token punctuation">,</span>arg1<span class="token punctuation">,</span>arg2<span class="token punctuation">,</span><span class="token operator">...</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token operator">-</span> Tham số đầu tiên sẽ là file python script<span class="token operator">-</span> theo sau sẽ là các arg tham số ta muốn truyền vào
Các tham số truyền vào sẽ được lấy ra theo đúng thứ tự123456<span class="token comment"># process.py</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"First name: "</span> <span class="token operator">+</span> sys<span class="token punctuation">.</span>argv<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">"Last name: "</span> <span class="token operator">+</span> sys<span class="token punctuation">.</span>argv<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
Chạy ựng dụng lên và sau đó nhập đường link ví dụ làhttp://localhost:3000/name?firstname=van&lastname=nghia
kết quả :trong console:
Cách 2: gọi Python script từ Node child process bằng cách sử dụng python-shell package
- Cách này có thể hiểu là cách 1.1 vì thực ra ta vẫn sử dụng child process nhưng lúc này chúng ta sẽ sử dụng python-shell để gộp các chi tiết triển khai (cũng như cung cấp xử lý lỗi và các tiện ích khác bao gồm triển khai một messaging đơn giản để giao tiếp trực tiếp với một script đơn) .Ta sẽ viết lại file server như sau:1234567891011121314151617<span class="token comment">// server.js</span>app<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'/name'</span><span class="token punctuation">,</span> callName<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">function</span> <span class="token function">callName</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> res<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">let</span> <span class="token punctuation">{</span> PythonShell <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'python-shell'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">var</span> options <span class="token operator">=</span> <span class="token punctuation">{</span>args<span class="token punctuation">:</span> <span class="token punctuation">[</span>req<span class="token punctuation">.</span>query<span class="token punctuation">.</span>firstname<span class="token punctuation">,</span> req<span class="token punctuation">.</span>query<span class="token punctuation">.</span>lastname<span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">;</span>PythonShell<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token string">'process.py'</span><span class="token punctuation">,</span> options<span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span> data<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>data<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>data<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span>
Install package
python-shell
:12npm i python-shell --savechạy để kiểm tra ta sẽ có kết quả :
Cách 3 : sử dụng một message broker
- Bây giờ chúng ta sẽ chạy ứng dụng Python và Node như các quy trình riêng biệt và sử dụng một message broker để giao tiếp giữa chúng . Ở đây chúng tôi sử dụng RabbitMQ, cùng với amqplib để tích hợp trong node và pika cho Python.Thực hiện theo cài đặt RabbitMQ nếu bạn chưa cài, trên OSX bạn có thể chạy một cách đơn giản:12345678sudo apt updatesudo apt -y install rabbitmq-serverpip install pikanpm install amqplib --save
Sau đó start
RabbitMQ
:12sudo systemctl start rabbitmq-server.serviceBây giờ chúng ra sẽ chỉnh sửa file
server.js
. Sử dụng amqplib trong node để kết nối đến RabbitMQ instance đang chạy:123456789101112131415161718192021222324252627282930<span class="token comment">//server.js</span>app<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'/name'</span><span class="token punctuation">,</span> callName<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">function</span> <span class="token function">callName</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> res<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">var</span> amqp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'amqplib/callback_api'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">var</span> input <span class="token operator">=</span> <span class="token punctuation">[</span>req<span class="token punctuation">.</span>query<span class="token punctuation">.</span>firstname<span class="token punctuation">,</span> req<span class="token punctuation">.</span>query<span class="token punctuation">.</span>lastname<span class="token punctuation">]</span><span class="token punctuation">;</span>amqp<span class="token punctuation">.</span><span class="token function">connect</span><span class="token punctuation">(</span><span class="token string">'amqp://localhost'</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span> conn<span class="token punctuation">)</span> <span class="token punctuation">{</span>conn<span class="token punctuation">.</span><span class="token function">createChannel</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span> ch<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">var</span> simulations <span class="token operator">=</span> <span class="token string">'simulations'</span><span class="token punctuation">;</span>ch<span class="token punctuation">.</span><span class="token function">assertQueue</span><span class="token punctuation">(</span>simulations<span class="token punctuation">,</span> <span class="token punctuation">{</span> durable<span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">var</span> results <span class="token operator">=</span> <span class="token string">'results'</span><span class="token punctuation">;</span>ch<span class="token punctuation">.</span><span class="token function">assertQueue</span><span class="token punctuation">(</span>results<span class="token punctuation">,</span> <span class="token punctuation">{</span> durable<span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>ch<span class="token punctuation">.</span><span class="token function">sendToQueue</span><span class="token punctuation">(</span>simulations<span class="token punctuation">,</span> Buffer<span class="token punctuation">.</span><span class="token keyword">from</span><span class="token punctuation">(</span><span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>input<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>ch<span class="token punctuation">.</span><span class="token function">consume</span><span class="token punctuation">(</span>results<span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span> <span class="token punctuation">{</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>msg<span class="token punctuation">.</span>content<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>msg<span class="token punctuation">.</span>content<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span> noAck<span class="token punctuation">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>conn<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span>Chúng ta viết một trình xử lý message đơn giản bằng Python để xử lý các request messages, gọi process.py và publish response messages – message.py:
1234567891011121314151617181920<span class="token keyword">import</span> pika<span class="token keyword">import</span> process<span class="token keyword">import</span> jsonconnection <span class="token operator">=</span> pika<span class="token punctuation">.</span>BlockingConnection<span class="token punctuation">(</span>pika<span class="token punctuation">.</span>ConnectionParameters<span class="token punctuation">(</span><span class="token string">'localhost'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>channel <span class="token operator">=</span> connection<span class="token punctuation">.</span>channel<span class="token punctuation">(</span><span class="token punctuation">)</span>channel<span class="token punctuation">.</span>queue_declare<span class="token punctuation">(</span>queue<span class="token operator">=</span><span class="token string">'simulations'</span><span class="token punctuation">)</span>channel<span class="token punctuation">.</span>queue_declare<span class="token punctuation">(</span>queue<span class="token operator">=</span><span class="token string">'results'</span><span class="token punctuation">)</span><span class="token keyword">def</span> <span class="token function">callback</span><span class="token punctuation">(</span>ch<span class="token punctuation">,</span> method<span class="token punctuation">,</span> properties<span class="token punctuation">,</span> body<span class="token punctuation">)</span><span class="token punctuation">:</span>requestParams <span class="token operator">=</span> json<span class="token punctuation">.</span>loads<span class="token punctuation">(</span>body<span class="token punctuation">.</span>decode<span class="token punctuation">(</span><span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>firstname <span class="token operator">=</span> <span class="token builtin">str</span><span class="token punctuation">(</span>requestParams<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span>lastname <span class="token operator">=</span> <span class="token builtin">str</span><span class="token punctuation">(</span>requestParams<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>results <span class="token operator">=</span> process<span class="token punctuation">.</span>simulate<span class="token punctuation">(</span>firstname<span class="token punctuation">,</span> lastname<span class="token punctuation">)</span>channel<span class="token punctuation">.</span>basic_publish<span class="token punctuation">(</span>exchange<span class="token operator">=</span><span class="token string">''</span><span class="token punctuation">,</span> routing_key<span class="token operator">=</span><span class="token string">'results'</span><span class="token punctuation">,</span> body<span class="token operator">=</span>json<span class="token punctuation">.</span>dumps<span class="token punctuation">(</span>results<span class="token punctuation">,</span> ensure_ascii<span class="token operator">=</span><span class="token boolean">False</span><span class="token punctuation">)</span><span class="token punctuation">)</span>channel<span class="token punctuation">.</span>basic_consume<span class="token punctuation">(</span>queue<span class="token operator">=</span><span class="token string">'simulations'</span><span class="token punctuation">,</span> on_message_callback<span class="token operator">=</span>callback<span class="token punctuation">,</span> auto_ack<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">)</span>channel<span class="token punctuation">.</span>start_consuming<span class="token punctuation">(</span><span class="token punctuation">)</span>Tiếp đến Chúng ta cần thực hiện một số thay đổi nhỏ đối với process.py – bây giờ chúng ta sẽ truyền các tham số vào, thay vì sử dụng sys.argvs và expose ra một method mà chúng ta có thể gọi từ message.py:
12345678910111213141516<span class="token comment"># process.py</span><span class="token keyword">import</span> sys<span class="token comment"># print("Output from Python") </span><span class="token comment"># print("First name: " + sys.argv[1]) </span><span class="token comment"># print("Last name: " + sys.argv[2])</span><span class="token keyword">def</span> <span class="token function">simulate</span><span class="token punctuation">(</span>firstname<span class="token punctuation">,</span> lastname<span class="token punctuation">)</span><span class="token punctuation">:</span>results <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token string">'firstname'</span><span class="token punctuation">:</span> firstname<span class="token punctuation">,</span><span class="token string">'lastname'</span><span class="token punctuation">:</span> lastname<span class="token punctuation">}</span><span class="token keyword">return</span> resultsCác bước để chạy thì đầu tiên ra sẽ run file
message.py
:12python message.pyrồi mới chạy đến server node:
12npm startKiểm tra kết quả
Kết Luận
Đây là một sự kết hợp đơn giản của Python và Node.js, điều này hữu ích cho các tình huống mà bạn muốn sử dụng các khả năng tính toàn của Python nhưng lại muốn tận dụng các lợi thế của ứng dụng Node.js. Mong rằng qua bài biết này các bạn có thể sử dụng và phát triển ứng dụng của mình tốt hơn từ những điều cơ bản này.
Source: https://github.com/ngovannghia1997kma/Node_integrate_Python
Nguồn :
https://medium.com/@HolmesLaurence/integrating-node-and-python-6b8454bfc272
https://www.geeksforgeeks.org/run-python-script-node-js-using-child-process-spawn-method/