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

Laravel 9运行Python脚本/EXE文件报无法创建临时目录错误

问题描述

在Laravel 9应用开发过程中,先后尝试通过exec()、shell_exec()函数、Symfony Process组件运行Python脚本及打包生成的exe可执行文件,所有方式均执行失败。调试时返回INTERNAL ERROR: cannot create temporary directory!错误,将可执行文件路径从原路径C:/Users/edwin/Documents/lectordocs/lectorDocs.exe更换为项目路径C:\xampp\htdocs\Login\login-laravel\public\assets\python后,相同报错仍然出现。

涉及代码

Python脚本

#!/usr/bin/env python

from re import L
import sys
import MySQLdb

miConexion = MySQLdb.connect( host='127.0.0.1', user= 'root', db='pruebas' )
cur = miConexion.cursor()
mySqlInsert = "INSERT INTO documentFin (co, localizacion, categoria, idItem, nombre, cantidad, fecha, lote) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)"

def insertarTabla(co, localizacion, categoria, idItem, nombre, cantidad, fecha, lote):
    val = (co, localizacion, categoria, idItem, nombre, cantidad, fecha, lote)
    try:
        cur.execute(mySqlInsert, val)
        miConexion.commit()
    except:
        print(val)
def verificarFecha(fecha):
    if(len(fecha) == 10):
        if(fecha[4] == "/" and fecha[7] == "/"):
            return True
        else:
            return False
    else:
        return False


def probar():
    with open("UCIN3053.p01") as archivo:
        lines = archivo.readlines()
    co = ""
    localizacion = ""
    categoria = ""
    contadorMas = 0
    matriz = []
    listaTemp = []
    for x in range(len(lines)):
        temp = lines[x].split()
        if(len(temp) > 1):
            if(temp[1] == "C.O."):
                co = temp[3] + " " + temp[4]
            elif(temp[1] == "Localizacion"):            
                local = temp[3:len(temp) - 1]
                
                
            elif(temp[1] == "Categoria"):
                categoria = temp[3] 

            if(temp[0].isnumeric()):
                if(temp[1].isnumeric()):
                    listaTemp.append(cod)
                    listaTemp.append(cadena)
                    listaTemp.append(temp[1])
                    listaTemp.append(temp[0])
                    listaTemp.append("")
                    matriz.append(listaTemp)
                    listaTemp = []
                elif(verificarFecha(temp[1])):
                    listaTemp.append(cod)
                    listaTemp.append(cadena)
                    listaTemp.append(temp[2])
                    listaTemp.append(temp[0])
                    listaTemp.append(temp[1])
                    matriz.append(listaTemp)
                    listaTemp = []
                else:
                    listaTemp.append(temp[0])
                    cod = temp[0]
                    cadena = ""
                    for x in range(1, len(temp)):
                        if(temp[x].isnumeric() and (temp[x + 1] == "UND" or temp[x + 1] == "FCO" or temp[x + 1] == "CJA" or temp[x + 1] == "FRA")):
                            numTemp = x
                            break
                        cadena += temp[x] + " "
                    listaTemp.append(cadena)   
                    listaTemp.append(temp[numTemp])
                    listaTemp.append("") 
                    listaTemp.append("")     
                    matriz.append(listaTemp)
                    listaTemp = []
            elif(temp[0] != "|"):
                if(temp[0][len(temp[0]) - 2]) == "-":
                    if(verificarFecha(temp[1])):
                        listaTemp.append(cod)
                        listaTemp.append(cadena)
                        listaTemp.append(temp[2])
                        listaTemp.append(temp[0])
                        listaTemp.append(temp[1])
                        matriz.append(listaTemp)
                        listaTemp = []
                    else:
                        listaTemp.append(cod)
                        listaTemp.append(cadena)
                        listaTemp.append(temp[1])
                        listaTemp.append(temp[0])
                        listaTemp.append("")
                        matriz.append(listaTemp)
                        listaTemp = []
        elif(len(temp) == 1):
            contadorMas += 1
        if(contadorMas == 4):
            contadorMas = 0
            for w in range(len(local)):
                localizacion += local[w] + " "

            #Añadir matriz e identificadores
            for x in range(len(matriz)):
                insertarTabla(co, localizacion, categoria, matriz[x][0], matriz[x][1], matriz[x][2], matriz[x][3], matriz[x][4])
            matriz = []
            localizacion = ""
    cur.close()
probar()

Laravel控制器代码

<?php

namespace App\Http\Controllers;

    use Illuminate\Http\Request;
    use Symfony\Component\Process\Process;
    use Symfony\Component\Process\Exception\ProcessFailedException;
    
    class InventarioController extends Controller
    {
        public function reportar(Request $request){
            $file = 'C:/Users/edwin/Documents/lectordocs/lectorDocs.exe';
            if(file_exists($file)){
                // echo 'File does exist  ::   ' . $file;
                $process = new Process([$file]);
                $process->run();
    
                // executes after the command finishes
                if (!$process->isSuccessful()) {
                    throw new ProcessFailedException($process);
                }
    
                return redirect()->to("/login");
    
                }
            else{
                return redirect()->to("/home");
            }   
        }
    }
报错原因

这个错误是PyInstaller单文件(onefile)模式打包的exe的典型运行错误:单文件模式打包的exe启动时,会默认向系统临时目录写入解压后的Python运行时、依赖库文件,创建_MEIxxxxxx格式的临时文件夹。如果PHP运行宿主(XAMPP环境下一般是Apache服务)的启动身份对系统临时目录没有写入权限、系统盘剩余空间不足,就会抛出该错误,和exe本身存放路径没有直接关系。
另外现有代码还存在工作目录不匹配的隐患:Python代码用相对路径读取UCIN3053.p01文件,Symfony Process默认继承PHP进程的工作目录,不是exe所在目录,即使临时目录问题修复,也会出现找不到文件的错误。

解决方案

按优先级依次排查处理:

  • 调整临时目录权限:找到系统临时目录(默认路径为C:\Windows\TEMP、C:\Users\<当前系统用户>\AppData\Local\Temp),给Apache服务的运行用户添加读取、写入、修改权限。测试阶段可以临时把Apache服务的登录身份改为本地管理员账户,确认问题根因是权限后再收敛到最小必要权限,不要长期用管理员权限运行Web服务。
  • 打包时指定自定义临时目录:重新用PyInstaller打包exe时,添加--runtime-tmpdir参数指定一个Web进程有权限写入的目录作为临时解压路径,示例打包命令:
    pyinstaller --onefile --runtime-tmpdir "C:\xampp\htdocs\Login\login-laravel\public\assets\python\tmp" lectorDocs.py
    
    提前手动创建好上述tmp目录,给该目录开放写入权限即可。
  • 显式设置Process工作目录:实例化Symfony Process后,调用setWorkingDirectory方法指定工作目录为exe和UCIN3053.p01文件所在的目录,避免相对路径找不到文件,修改后的代码片段:
    $process = new Process([$file]);
    // 替换为你的文件实际存放目录
    $process->setWorkingDirectory('C:\xampp\htdocs\Login\login-laravel\public\assets\python');
    $process->run();
    
  • 更换打包模式:放弃onefile单文件打包模式,改用onedir模式生成包含所有依赖的文件夹,exe启动时不需要解压临时文件,从根源上规避临时目录创建问题。
  • 检查磁盘空间:确认系统盘剩余空间大于1G,磁盘满也会导致临时目录创建失败。

内容的提问来源于stack exchange,提问作者Pipe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 16:36:27