如何在SvelteKit应用中使用已有.venv虚拟环境运行Python脚本
在SvelteKit中正确使用指定Python虚拟环境执行脚本
问题背景
原本在SvelteKit应用中通过exec执行Python脚本,命令如下:
const command = `python "${pythonScriptPath}" ${plateID} "${formattedProdDate}"`;
需要改为在已创建的虚拟环境中执行脚本:
- 已在Python脚本所在目录
C:\scripts\HTLReportScript创建.venv虚拟环境,通过pipenv install配置完成 - 本地进入该目录执行
pipenv run python get-pdf.py string date可正常运行
但在SvelteKit中修改命令为pipenv run python "${pythonScriptPath}" ${plateID} "${formattedProdDate}"时,系统会为SvelteKit创建新虚拟环境,而非使用脚本目录下已有的环境。
原执行代码
import fs from 'fs/promises'; import { exec } from 'node:child_process'; import { prisma } from "$lib/server/prisma.js"; import { format } from 'date-fns'; export async function GET({ url }: { url: { searchParams: URLSearchParams } }) { const plateID = url.searchParams.get('plateID') || ''; console.log('Plate id:', plateID); // 从数据库获取生产结束日期 const prodEndDateRaw = await prisma.$queryRaw<{ PROD_END: Date }[]>` SELECT PROD_END FROM LTDB.LTDB.PIECE_TIMES pt WHERE ID_PIECE = ${plateID} `; // 类型转换并检查生产结束日期是否存在 const prodEndDate = prodEndDateRaw[0]?.PROD_END as Date | undefined; if (prodEndDate) { // 格式化生产结束日期 const formattedProdDate = format(prodEndDate, 'yyyy-MM-dd'); console.log(formattedProdDate); const pythonScriptPath = 'C:\\scripts\\HTLReportScript\\get-pdf.py'; // 执行Python脚本的命令(未使用虚拟环境) const command = `python "${pythonScriptPath}" ${plateID} "${formattedProdDate}"`; try { console.log('正在执行Python脚本...'); await new Promise<void>((resolve, reject) => { exec(command, (error, stdout, stderr) => { if (error) { console.error(`执行Python脚本出错: ${error.message}`); console.error('Python脚本错误输出:', stderr); reject(error); } else { console.log('Python脚本执行完成:', stdout); resolve(); } }); }); } catch (error: any) { console.error('错误:', error.message); return createServerErrorResponse('内部服务器错误'); } // 读取生成的PDF文件 const localDestination = `C:\\scripts\\HTLReportScript\\Piece_${plateID}.pdf`; const fileData = await readFile(localDestination); // 设置响应头 const headers = { 'Content-Disposition': `attachment; filename=Piece_${plateID}.pdf`, 'Content-Type': 'application/pdf', }; // 发送文件后删除本地文件(注释状态) // await fs.unlink(localDestination); // 返回PDF文件给客户端 return new Response(fileData, { headers }); } else { console.error('错误: 未找到生产结束日期'); return createServerErrorResponse('内部服务器错误'); } } async function readFile(filePath: string): Promise<Buffer> { try { const data = await fs.readFile(filePath); return data; } catch (error: any) { console.error(`读取文件出错: ${error.message}`); throw new Error('内部服务器错误'); } } function createServerErrorResponse(message: string) { return new Response(JSON.stringify({ error: message }), { status: 500, headers: { 'Content-Type': 'application/json' }, }); }
解决方案
直接切换到脚本目录,激活已有的虚拟环境后执行脚本,修改command变量为:
const command = `cd C:\\scripts\\HTLReportScript && C:\\scripts\\HTLReportScript\\.venv\\Scripts\\activate && python get-pdf.py ${plateID} ${formattedProdDate}`;
更新后的完整代码
import fs from 'fs/promises'; import { exec } from 'node:child_process'; import { prisma } from "$lib/server/prisma.js"; import { format } from 'date-fns'; export async function GET({ url }: { url: { searchParams: URLSearchParams } }) { const plateID = url.searchParams.get('plateID') || ''; console.log('Plate id:', plateID); // 从数据库获取生产结束日期 const prodEndDateRaw = await prisma.$queryRaw<{ PROD_END: Date }[]>` SELECT PROD_END FROM LTDB.LTDB.PIECE_TIMES pt WHERE ID_PIECE = ${plateID} `; // 类型转换并检查生产结束日期是否存在 const prodEndDate = prodEndDateRaw[0]?.PROD_END as Date | undefined; if (prodEndDate) { // 格式化生产结束日期 const formattedProdDate = format(prodEndDate, 'yyyy-MM-dd'); console.log(formattedProdDate); const pythonScriptPath = 'C:\\scripts\\HTLReportScript\\get-pdf.py'; // 执行Python脚本的命令(使用指定虚拟环境) const command = `cd C:\\scripts\\HTLReportScript && C:\\scripts\\HTLReportScript\\.venv\\Scripts\\activate && python get-pdf.py ${plateID} ${formattedProdDate}`; try { console.log('正在执行Python脚本...'); await new Promise<void>((resolve, reject) => { exec(command, (error, stdout, stderr) => { if (error) { console.error(`执行Python脚本出错: ${error.message}`); console.error('Python脚本错误输出:', stderr); reject(error); } else { console.log('Python脚本执行完成:', stdout); resolve(); } }); }); } catch (error: any) { console.error('错误:', error.message); return createServerErrorResponse('内部服务器错误'); } // 读取生成的PDF文件 const localDestination = `C:\\scripts\\HTLReportScript\\Piece_${plateID}.pdf`; const fileData = await readFile(localDestination); // 设置响应头 const headers = { 'Content-Disposition': `attachment; filename=Piece_${plateID}.pdf`, 'Content-Type': 'application/pdf', }; // 发送文件后删除本地文件 await fs.unlink(localDestination); // 返回PDF文件给客户端 return new Response(fileData, { headers }); } else { console.error('错误: 未找到生产结束日期'); return createServerErrorResponse('内部服务器错误'); } } async function readFile(filePath: string): Promise<Buffer> { try { const data = await fs.readFile(filePath); return data; } catch (error: any) { console.error(`读取文件出错: ${error.message}`); throw new Error('内部服务器错误'); } } function createServerErrorResponse(message: string) { return new Response(JSON.stringify({ error: message }), { status: 500, headers: { 'Content-Type': 'application/json' }, }); }
内容的提问来源于stack exchange,提问作者Avi4nFLu
相关产品推荐
相关产品推荐

