如何让Node.js异步函数与Python子进程协同运行?
问题原因分析
你的Python代码卡在proc.communicate()这一步,是因为该方法会阻塞等待子进程完全退出,但Node.js的app.js中fs.watchFile设置了persistent: true,会持续保持进程运行不退出,导致Python主线程被永久阻塞。用asyncio无效是因为subproc函数里的communicate()仍是同步阻塞操作,异步框架没发挥作用。
同时你的app.js存在两处语法错误:
- 变量名错误:
policies_file应该是text_file - 语法不闭合:
fs.watchFile回调后缺少)和;,main函数定义缺少闭合}
解决方案一:修改Python代码,异步运行Node子进程不阻塞
通过asyncio.subprocess或线程实现异步处理子进程输出,让Python主线程可以同时执行GPIO代码。
基于asyncio的改进代码
import subprocess import asyncio async def read_node_output(proc): # 异步读取Node.js子进程的输出 while True: line = await proc.stdout.readline() if not line: break print(f"Node.js输出: {line.decode('utf-8').strip()}") async def start_node_proc(): print("start subprocess") # 使用asyncio创建非阻塞子进程 proc = await asyncio.create_subprocess_exec( "/usr/bin/node", "/home/user/git/corp/prudens-js/node/app.js", stdout=subprocess.PIPE ) print("after start") # 启动异步读取输出的任务(不阻塞主线程) asyncio.create_task(read_node_output(proc)) return proc async def gpio_task(): # 替换为你的实际GPIO逻辑 print("GPIO任务启动") while True: await asyncio.sleep(2) print("GPIO操作执行中...") async def main(): print("start") # 同时启动Node子进程和GPIO任务 await asyncio.gather(start_node_proc(), gpio_task()) asyncio.run(main())
基于线程的改进代码(适合不熟悉asyncio的场景)
import subprocess import threading import time def read_node_output(proc): for line in iter(proc.stdout.readline, b''): print(f"Node.js输出: {line.decode('utf-8').strip()}") def start_node_proc(): print("start subprocess") proc = subprocess.Popen( ["/usr/bin/node", "/home/user/git/corp/prudens-js/node/app.js"], stdout=subprocess.PIPE ) print("after start") # 用线程后台读取输出,不阻塞主线程 threading.Thread(target=read_node_output, args=(proc,), daemon=True).start() return proc def gpio_task(): print("GPIO任务启动") while True: time.sleep(2) print("GPIO操作执行中...") if __name__ == "__main__": print("start") proc = start_node_proc() # 用线程启动GPIO任务 threading.Thread(target=gpio_task, daemon=True).start() # 主线程保持运行,按回车可终止所有进程 input("按回车退出程序\n") proc.terminate()
解决方案二:改用Node.js调用Python GPIO代码
如果Node.js的文件监控逻辑已经成熟,可以让Node.js作为主进程,通过child_process模块调用Python的GPIO脚本,架构更符合Node.js的异步IO特性。
修复后的app.js
const fs = require('fs'); const { spawn } = require('child_process'); function main() { const text_file= '/home/user/git/corp/file.txt'; // 修复变量名错误 const text = fs.readFileSync(text_file, "utf8"); console.log(text); // 修复语法闭合问题 fs.watchFile(text_file, {bigint: false, persistent: true, interval: 1}, (curr, prev) => { const text= fs.readFileSync(text_file, "utf8"); console.log(text); }); // 启动Python GPIO子进程 const gpioProc = spawn('python3', ['/home/user/git/corp/gpio_script.py']); // 监听Python输出 gpioProc.stdout.on('data', (data) => { console.log(`Python GPIO输出: ${data.toString().trim()}`); }); // 监听Python错误输出 gpioProc.stderr.on('data', (data) => { console.error(`Python错误: ${data.toString().trim()}`); }); } main();
Python GPIO脚本(gpio_script.py)
import time print("Python GPIO进程启动") while True: # 替换为你的实际GPIO控制代码 print("执行GPIO操作") time.sleep(2)
方案对比
- Python调用Node.js:适合已有成熟Python GPIO代码,不想大量改动的场景,需注意异步/线程处理避免阻塞。
- Node.js调用Python:适合Node.js文件监控逻辑完善的场景,Node.js的异步特性更适配文件监控需求,架构更清晰。
内容的提问来源于stack exchange,提问作者verpas
相关产品推荐
相关产品推荐

