Node.js调用Python的后端部署Vercel遇spawn ENOENT错误求助
解决Vercel部署Node.js调用Python脚本的spawn ENOENT错误
问题核心
Vercel的Node运行时环境未预装Python,且Node与Python运行时完全隔离,跨Runtime调用Python脚本不符合Vercel的部署模型,导致spawn python找不到可执行文件。
修复方案:重构为Python Serverless Function
放弃Node调用Python的方式,直接用Vercel的Python Serverless Function处理摘要请求,步骤如下:
1. 创建Python Serverless Function
在项目根目录新建api/summary.py(Vercel默认识别api/目录下的文件为Serverless Functions),整合原Python脚本与Node中的逻辑:
import json import math import nltk from sumy.summarizers.luhn import LuhnSummarizer from sumy.parsers.plaintext import PlaintextParser from sumy.nlp.tokenizers import Tokenizer from nltk.tokenize import sent_tokenize # 自动下载nltk所需的tokenizer数据 try: nltk.data.find('tokenizers/punkt') except LookupError: nltk.download('punkt') def handler(event, context): # 解析请求体 req_body = json.loads(event['body']) text = req_body['text'] len_param = int(req_body['length']) word_counter = len(text.split(" ")) sum_vals = { 1: [30, 130], 2: [100, 300], 3: [150, 400], 4: [200, 500] } # 处理不同长度参数的逻辑 if len_param == 0: # 生成带项目符号的摘要 sentences = sent_tokenize(text) parser = PlaintextParser.from_string(text, Tokenizer("english")) summarizer_luhn = LuhnSummarizer() summary = summarizer_luhn(parser.document, int(math.ceil(len(sentences)/3))) document_parser = [str(i) for i in summary] final_sentence = "\n".join([f"\u2022 {doc}" for doc in document_parser]) else: # 处理指定长度的摘要 target_len = len_param if target_len == 1: if word_counter < sum_vals[1][0]: return { 'statusCode': 400, 'headers': {'Access-Control-Allow-Origin': '*'}, 'body': json.dumps({'error': 'This sentence is too short to summarize.'}) } use_vals = sum_vals[1] else: use_vals = sum_vals[target_len] if word_counter >= sum_vals[target_len][0] else sum_vals[target_len-1] sentences = sent_tokenize(text) parser = PlaintextParser.from_string(text, Tokenizer("english")) summarizer_luhn = LuhnSummarizer() summary_sentence_count = int(math.ceil(len(sentences)/3)) summary = summarizer_luhn(parser.document, summary_sentence_count) document_parser = [str(i) for i in summary] final_sentence = "\n".join(document_parser) # 返回结果 return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json' }, 'body': json.dumps({'summary': final_sentence}) }
2. 配置Python依赖
在项目根目录新建requirements.txt,列出所有依赖包:
sumy nltk
3. 修改Vercel配置文件
更新vercel.json,简化路由规则:
{ "version": 2, "routes": [ { "src": "/summary", "dest": "/api/summary.py", "methods": ["POST"], "headers": { "Access-Control-Allow-Origin": "*" } } ] }
4. 调整前端请求
修改前端的请求路径,指向Vercel的Python Serverless Function:
// 移除自定义headers(后端已配置),修改请求路径 let result = await Axios.post(url + "/api/summary", data) .then((res) => { console.log("Then 1", res.data) return res.data.summary }) .then((result) => { console.log("Then 2", result) document.getElementsByClassName("text-output")[0].value = result setloadingSubmit(false) return result }) .catch((err) => { console.log("There was an error: ", err) setloadingSubmit(false) return "Error" })
关键说明
- Vercel的Node与Python运行时完全隔离,无法通过
child_process跨Runtime调用脚本,必须将Python逻辑转为独立的Serverless Function。 - 原代码中的Hex编码可移除,直接返回字符串即可避免编码问题。
- 新增NLTK数据自动下载逻辑,避免部署后因缺少tokenizer数据报错。
内容的提问来源于stack exchange,提问作者kimberly modeste
相关产品推荐
相关产品推荐

