【Python 使用 subprocess 调用本地 Node.js 脚本、互通数据完整教程】
Python 使用 subprocess 调用本地 Node.js 脚本、互通数据完整教程
核心原理
- Python 通过
subprocess新建子进程执行node xxx.js - JS 脚本通过 标准输出 stdout 把数据传给 Python(推荐 JSON 序列化,支持对象 / 数组 / 数字)
- Python 读取 stdout 字符串,
json.loads()解析拿到结构化数据 - 双向传参:Python 可通过命令行参数、标准输入 stdin 向 JS 传递数据
环境前提
- 本地已安装 Node.js,终端输入
node -v能正常输出版本号 - Python 3.x,内置
subprocess、json无需额外安装
下面使用python与javascript双向数据互通的示例,来演示本篇文章的学习:
demo.js
function test(a, b, c) {
return a + b + c
};
// 接受subprocess传来的参数
arg1 = process.argv.slice(2)[0]
arg2 = process.argv.slice(2)[1]
arg3 = process.argv.slice(2)[2]
console.log(test(arg1, arg2, arg3))
demo.py
import subprocess
arg1 = 'python'
arg2 = '调用'
arg3 = 'js'
js_result = subprocess.run(['node', 'demo.js', arg1, arg2, arg3], capture_output=True, text=True, encoding='utf8')
# 手动判断退出码
if js_result.returncode == 0:
print("标准输出:\n", js_result.stdout)
else:
print("错误输出:\n", js_result.stderr)
在deomo.js和demo.py文件中,py文件向js文件中的代码传递了arg1,arg2,arg3三个参数,而js文件向py文件中的代码传递了console.log(......)数据。

看了以上示例,就知道这里面的关键传输渠道就是subprocess.run,所以,下面我们就来学习一下subprocess.run:
subprocess.run(
args=["node", "xxx.js"], # 命令列表,推荐列表形式避免shell注入漏洞
capture_output=True, # 捕获stdout和stderr
stdout=subprocess.PIPE, # 单独捕获标准输出
stderr=subprocess.PIPE, # 单独捕获错误输出
text=True / universal_newlines=True, # 输出为字符串,否则是字节流
input="xxx", # 写入子进程标准输入
timeout=10, # 超时时间,秒
shell=False, # 默认False,安全;True会启动shell,有注入风险
cwd="./scripts" # 指定node脚本所在工作目录,文件路径可写相对路径
)
方法详解
-
['node', 'demo.js', 'arg1', 'arg2', 'args3']: 命令和参数的列表。node是命令,可以传node(会在系统变量中寻找node.exe),也可以传node.exe的所在路径,demo.js是要执行的文件,arg1,arg2,arg3是传递给 JS 脚本的参数,命令和参数的类型必须是字符串,否则报错。 -
capture_output=True: 捕获子进程的标准输出 (stdout) 和标准错误 (stderr)。而不是出错直接在控制台输出 -
text=True: 将捕获的输出从字节(bytes)解码为字符串(str) -
check:True:若子进程返回非零退出码(表示错误),自动抛出CalledProcessError异常。False(默认):不检查退出码,需手动判断result.returncode。
-
timeout:设置超时时间(秒),超时后终止子进程并抛出异常。 -
input:传递给子进程的输入内容(需配合text=True使用字符串,否则用bytes)。
capture_output=True 等价于同时设置 stdout=subprocess.PIPE 和 stderr=subprocess.PIPE,所以即使你没手动写 stdout=subprocess.PIPE,底层也自动开启了标准输出捕获,自然也能拿到 JS 的 console.log 内容。
进阶 1:Python 传参数给 JS(命令行传参)
1、核心原理
subprocess 执行命令时,参数放在列表 [] 里,列表第二个元素是执行程序,后面全部都是传给 Node 的参数,会被 process.argv 读取。
process.argv 说明:
process.argv[0] → node 程序路径
process.argv[1] → 执行的js文件路径
process.argv[2]、[3]... → Python 传入的自定义参数
2、标准语法格式
Python 传参格式
subprocess.run(["node", "脚本.js", "参数1", "参数2", "数字3"])
多类型通用:字符串、数字全部转字符串传入。
3、示例 1:基础字符串 + 数字传参
js 文件 run.js
// 获取命令行传入参数
let name = process.argv[2];
let age = Number(process.argv[3]);
// 返回结果
const res = {
user: name,
age: age,
total: age * 10
};
// 输出JSON给Python
console.log(JSON.stringify(res));
Python 调用 main.py
import subprocess
import json
# 向js传递参数:姓名、年龄
cmd = [
"node",
"run.js",
"张三",
"25"
]
# 执行并读取输出
result = subprocess.run(cmd, capture_output=True, text=True)
data = json.loads(result.stdout)
print(data)
{"user": "张三", "age": 25, "total": 250}
4、示例 2:一次性传递多个参数(数组批量传参)
Python 多参数
import subprocess, json
# 多参数统一打包
params = ["小明", "18", "北京", "99"]
cmd = ["node", "run.js", *params]
res = subprocess.run(cmd, capture_output=True, text=True)
print(json.loads(res.stdout))
js 读取多个参数
let name = process.argv[2];
let age = process.argv[3];
let city = process.argv[4];
let score = process.argv[5];
let obj = { name, age, city, score };
console.log(JSON.stringify(obj));
进阶 2:传递复杂对象(stdin 标准输入传 JSON)
- JS 作为主进程调用 Python 子进程(JS 写 stdin,读 stdout)
- Python 作为主进程调用 JS 子进程(Python 写 stdin,读 stdout)
基础 API 总览
1. Python stdin/stdout 操作
模块
sys.stdin:标准输入(读)sys.stdout:标准输出(写)json:序列化 / 反序列化复杂对象(字典、列表、嵌套对象)subprocess:创建子进程调用 Node/Python
在 Python 中操作标准输入(stdin)、标准输出(stdout)和标准错误(stderr)是日常开发中非常基础且重要的技能。
读取 stdin
import sys
# 1. 逐行读取(适合处理大文件或管道输入)
for line in sys.stdin:
print(f"收到: {line.strip()}")
if line.strip() == "exit":
break
# 2. 读取所有内容(直到 EOF,适合管道 `cat file.txt | python script.py`)
# content = sys.stdin.read()
# 3. 读取指定字节数
# chunk = sys.stdin.read(1024)
写入 stdout / stderr
import sys
# 写入标准输出(注意:需要手动加 \n,且写入的必须是字符串)
sys.stdout.write("这是一条标准输出\n")
sys.stdout.flush() # 强制刷新缓冲区(在重定向到文件时尤为重要)
# 写入标准错误(通常用于报错信息,避免污染正常的输出流)
sys.stderr.write("发生了一个错误!\n")
2. Node.js stdin/stdout 操作
模块
process.stdin:标准输入流process.stdout:标准输出流JSON.parse/JSON.stringify:序列化对象
process.stdin.on 是 Node.js 中用于监听标准输入流(Readable Stream)事件的方法。因为 process.stdin 本质上是一个可读流,你可以通过它来监听不同的生命周期事件,从而以事件驱动的方式处理输入数据。process.stdin.on 最常监听的几个核心事件及其实战用法:1. 监听 data 事件(最常用)
data 事件是最直接的方式。注意: 一旦绑定了 data 事件,流会自动从暂停模式切换到流动模式。// 建议先设置编码,否则读取到的是 Buffer 对象
process.stdin.setEncoding('utf8');
process.stdin.on('data', (chunk) => {
console.log(`接收到数据块: ${chunk}`);
});
2. 监听 end 事件
Ctrl+D,或管道输入完毕)。通常与 data 事件配合使用,用于执行清理操作或输出最终结果。let fullData = '';
process.stdin.setEncoding('utf8');
process.stdin.on('data', (chunk) => {
fullData += chunk;
});
process.stdin.on('end', () => {
console.log('输入结束,完整数据为:', fullData);
});
3. 监听 readable 事件(手动拉取模式)
readable 事件,并在内部手动调用 read() 方法。process.stdin.on('readable', () => {
let chunk;
// 使用 while 循环确保把缓冲区内的数据全部读完
while ((chunk = process.stdin.read()) !== null) {
console.log(`手动读取到: ${chunk.toString()}`);
}
});
4. 监听 error 事件
process.stdin.on('error', (err) => {
console.error('标准输入发生错误:', err.message);
});

浙公网安备 33010602011771号