Node调用Python脚本时相对导入失败问题求助
问题场景
开发Node.js后端应用时,通过child_process.spawn调用Python机器学习脚本,遇到跨文件夹导入自定义类的问题。当前临时通过修改sys.path和切换目录解决,但希望获得更优雅的实现方式。目录结构如下:
App | |-Backend | |-Node server.js |-Python | |-Classes image.py |-Functions upload.py
Python、Functions、Classes目录均包含__init__.py文件。
1. 为什么from Classes import image会报"No module named Classes"?
Python的模块搜索路径(sys.path)默认包含当前工作目录。从Node/server.js调用Python脚本时,默认工作目录是Node文件夹,而Classes目录位于Backend/Python下,不在sys.path的搜索范围内,Python无法定位到该模块,因此抛出错误。
2. 为什么from .image import Image会报"attempted relative import with no known parent package"?
相对导入(以.或..开头)依赖于当前模块的__package__属性,只有当脚本被当作包的子模块加载时,这个属性才会被正确设置。如果直接运行脚本文件(或通过spawn直接调用脚本路径),Python会将其视为顶层脚本,此时__package__为None,没有父包上下文,相对导入无法生效,触发该错误。
另外你之前尝试的-m参数用法错误:-m后需跟模块名(如Functions.upload),而非文件路径(../Python/Functions/upload.py),错误的参数导致Python无法正确识别模块,因此没有输出。
优雅解决方案
方案1:指定工作目录并正确使用-m参数
将spawn的工作目录(cwd)设置为Backend/Python,以模块名形式调用脚本,此时Python会将Python目录视为顶层包目录,Classes和Functions均为其子包:
const path = require('path'); const { spawn } = require('child_process'); const py = spawn('python', ['-m', 'Functions.upload', stringifiedData], { cwd: path.join(__dirname, '../Python') // 切换到Backend/Python目录 });
此时在upload.py中可直接使用:
from Classes import image
方案2:设置PYTHONPATH环境变量
调用Python脚本时,将PYTHONPATH环境变量设为Backend/Python目录,让Python自动将该目录加入模块搜索路径,无需切换工作目录:
const path = require('path'); const { spawn } = require('child_process'); const pythonRoot = path.join(__dirname, '../Python'); const py = spawn('python', [path.join(pythonRoot, 'Functions/upload.py'), stringifiedData], { env: { ...process.env, PYTHONPATH: pythonRoot } });
同样可在upload.py中直接用from Classes import image完成导入。
内容的提问来源于stack exchange,提问作者collectedcucumber4

