Nodejs与Python进行双向通信过程是什么
Admin 2022-07-18 群英技术资讯 290 次浏览
最简单粗暴的通信方式是 Nodejs调用一下 Python 脚本,然后获取子进程的输出,但是由于每次 Python 启动并加载数据包的过程比较漫长,所以对该过程优化。
index.py
# 封装的 Python 包, 体积巨大 from mb import MB # 从数据包中查询 mbe.get('1.0.1.0')
index.js
const { spawn } = require('child_process'); const ls = spawn('python3', ['index.py']); ls.stdout.on('data', (data) => { console.log(`stdout: ${data}`); }); ls.stderr.on('data', (data) => { console.error(`stderr: ${data}`); }); ls.on('close', (code) => { console.log(`child process exited with code $[code]`); });
通过child_process.spawn来派生 Python 子进程,监听 stdout 输出。上述方式也是官方文档中的示例,目前该示例存在两个问题:
保证一次数据加载,多次使用的前提是 Python 进程启动后不能退出。Python 进程之所以退出是因为无事可做,所以常见的手段有循环,sleep,监听端口,这些手段可以翻译成同步阻塞任务,同步非阻塞任务,其中代价最小的就是同步非阻塞任务,然后可以想到 Linux 的 select,epoll,简单搜索了下 Python 的 epoll,好像还有原生的包。
index.py - 通过 epoll 监听 stdin
import sys import fcntl import select from mb import MB import json mbe = MB('./data') # epoll 模型 fd = sys.stdin.fileno() epoll = select.epoll() epoll.register(fd, select.EPOLLIN) try: while True: events = epoll.poll(10) # 同步非阻塞 data = '' for fileno, event in events: data += sys.stdin.readline() # 通过标准输入获取数据 if data == '' or data == '\n': continue items = xxx # 数处理过程 for item in items: result = mbe.get(item) sys.stdout.write(json.dumps(result, ensure_ascii=False) +'\n') # 写入到标准输出 sys.stdout.flush() # 缓冲区刷新 finally: epoll.unregister(fd) epoll.close()
index.js - 通过 stdin 发送数据
const child_process = require('child_process'); const child = child_process.spawn('python3', ['./base.py']); let callbacks = [], chunks=Buffer.alloc(0), chunkArr = [], data = '', onwork = false; // buffer 无法动态扩容 child.stdout.on('data', (chunk) => { chunkArr.push(chunk) if (onwork) return; onwork = true; while(chunkArr.length) { chunks = Buffer.concat([chunks, chunkArr.pop()]); const length = chunks.length; let trunkAt = -1; for(const [k, d] of chunks.entries()) { if (d == '0x0a') { // 0a 结尾 data += chunks.slice(trunkAt+1, trunkAt=k); const cb = callbacks.shift(); cb(null, data === 'null' ? null : data ) data = ''; } } if (trunkAt < length) { chunks = chunks.slice(trunkAt+1) } } onwork = false; }) setInterval(() => { if (callbacks.length) child.stdin.write(`\n`); // Nodejs端的标准输入输出没有flush方法,只能 hack, 写入后python无法及时获取到最新 }, 500) exports.getMsg = function getMsg(ip, cb) { callbacks.push(cb) child.stdin.write(`${ip}\n`); // 把数据写入到子进程的标准输入 }
Python 与 Nodejs 通过 stdio 实现通信; Python 通过 epoll 监听 stdin 实现驻留内存,长时间运行。
虽然可以实现 Nodejs 和 Python 的双向通信,然后由于上述种种问题,在这里并不推荐使用这种方式,通过 HTTP 或 Socket 方式比这个香多了。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要给大家介绍了关于JavaScript中变量提升和函数提升的相关资料,以及JS变量提升和函数提升的顺序,文中给出了详细的介绍,需要的朋友可以参考下
这篇文章主要为大家介绍了vue中filter的应用场景,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助<BR>
本篇文章给大家带来了关于javascript的相关知识,其中主要介绍了关于旋转数组的相关问题,包括了什么是旋转数组、环状替换等等内容,下面一起来看一下,希望对大家有帮助。
这篇文章主要介绍了Vue实现下拉滚动加载数据的示例,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下
这篇文章给大家分享的是jQuery怎么取消hover事件的方法。在实际的项目中,我们常常需要用jquery去响应鼠标的hover事件,所以掌握绑定和取消hover事件是很基础的,文中的示例代码介绍得很详细,有需要的朋友可以参考,接下来就跟随小编一起了解看看吧。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008