You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 20:52:03