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

使用PyInstaller打包Tkinter多文件应用时遇递归深度超限错误求助

如何解决PyInstaller打包Tkinter多文件应用时的递归深度超出错误?

我用Python的Tkinter编写了一个多文件媒体应用,主文件通过subprocess将各个子文件与对应按钮关联,代码运行完全符合预期,但使用PyInstaller将应用转换为.exe文件时,出现“maximum recursion depth exceeded while calling a python object”错误,请问如何将我的.py文件成功转换为.exe?

主文件代码(main.py)

import tkinter as tk
from tkinter import ttk
import subprocess

class PlayerExApp:
    def __init__(self, master):
        self.master = master
        master.title("Player Ex | Media Player")
        master.geometry("1280x720")  # 设置初始窗口大小

        self.create_widgets()

    def create_widgets(self):
        # 创建根窗口框架
        root_frame = ttk.Frame(self.master, padding="10", style="White.TFrame")
        root_frame.pack(fill=tk.BOTH, expand=True)

        # 创建左侧框架
        left_frame = ttk.Frame(root_frame, style="White.TFrame")
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=False, padx=(75, 75))

        # 创建"Media"标题标签
        heading_label = ttk.Label(left_frame, text="Media", font=("Arial", 20, "bold"), style="Black.TLabel")
        heading_label.pack(pady=(50, 20))

        # 创建左侧按钮组
        left_buttons = ttk.Frame(left_frame, style="White.TFrame")
        left_buttons.pack()

        for text, command in [("音频播放器", "audio-player.py"),
                              ("视频播放器", "video-player.py")]:
            button = ttk.Button(left_buttons, text=text, style="Grey.TButton",
                                command=lambda c=command: self.on_button_press(c))
            button.pack(ipadx=90, pady=(0, 10))

        # 创建"Features"标题标签
        heading_label = ttk.Label(left_frame, text="功能", font=("Arial", 20, "bold"), style="Black.TLabel")
        heading_label.pack(pady=(50, 20))

        # 创建功能按钮组
        left_buttons = ttk.Frame(left_frame, style="White.TFrame")
        left_buttons.pack()

        for text, command in [("音频剪辑", "audio-clipper.py"),
                              ("MP3转换", "video-converter.py"),
                              ("提取人声", "root.py"),
                              ("视频增强", "enhance-video.py")]:
            button = ttk.Button(left_buttons, text=text, style="Grey.TButton",
                                command=lambda c=command: self.on_button_press(c))
            button.pack(ipadx=90, pady=(0, 10))

        # 创建右侧框架
        right_frame = ttk.Frame(root_frame, style="Black.TFrame")
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

        # 加载并调整Logo图片
        logo_img = tk.PhotoImage(file="images/logo.png")
        logo_img = logo_img.subsample(2)  # 缩小一半
        logo_label = ttk.Label(right_frame, image=logo_img)
        logo_label.image = logo_img
        logo_label.pack(side=tk.RIGHT, padx=300, expand=False)

        # 设置窗口响应式布局
        self.master.columnconfigure(0, weight=1)
        root_frame.columnconfigure(0, weight=1)
        left_frame.columnconfigure(0, weight=1)
        right_frame.columnconfigure(0, weight=1)
        self.master.rowconfigure(0, weight=1)

    def on_button_press(self, command):
        print(f"触发命令: {command}")
        subprocess.run(["python", command])

def main():
    root = tk.Tk()
    app = PlayerExApp(root)
    root.mainloop()

if __name__ == '__main__':
    main()

问题根源

  1. 打包后的exe无法通过subprocess.run(["python", command])找到Python环境,且子.py文件未被打包进exe,导致调用失败,进而触发递归错误(可能是错误处理逻辑或重复调用引发的循环)。
  2. PyInstaller单文件模式下,子进程无法直接访问原.py文件,且目标系统不一定安装Python。

解决方法

方案一:合并所有模块为单exe

将所有子文件打包进同一个exe,直接导入执行子模块,而非调用外部Python命令:

  1. 修改主文件的on_button_press方法:
import sys
import importlib

def on_button_press(self, command):
    print(f"触发命令: {command}")
    # 移除.py后缀,导入子模块
    module_name = command.replace('.py', '')
    # 动态导入模块
    module = importlib.import_module(module_name)
    # 执行子模块的main函数(需确保每个子文件都有main入口)
    module.main()
  1. 确保每个子文件(如audio-player.py)都有main()入口:
# 以audio-player.py为例
def main():
    root = tk.Tk()
    # 子文件的原有初始化代码
    root.mainloop()

if __name__ == '__main__':
    main()
  1. 执行打包命令:
pyinstaller --onefile --windowed --add-data "images/*;images" main.py audio-player.py video-player.py audio-clipper.py video-converter.py root.py enhance-video.py
  • --onefile:生成单exe文件
  • --windowed:隐藏命令行窗口
  • --add-data:打包图片资源(Windows用;分隔路径,Linux/macOS用:)

方案二:多文件模式打包

保留子文件的独立结构,打包后将子文件复制到exe目录:

  1. 修改主文件的on_button_press方法,用当前运行环境的解释器调用子文件:
import sys

def on_button_press(self, command):
    print(f"触发命令: {command}")
    # 使用sys.executable指向当前运行的Python解释器或打包后的exe
    subprocess.run([sys.executable, command])
  1. 执行打包命令:
pyinstaller --windowed --add-data "images/*;images" main.py
  1. 将所有子.py文件(audio-player.py、video-player.py等)复制到生成的dist目录下,与exe文件同级。

额外注意事项

  • 递归错误也可能源于Tkinter样式的循环引用,检查自定义Style是否存在互相依赖的情况,如有需调整。
  • 调试时可去掉--windowed参数,查看命令行输出的具体错误信息。
  • 确保所有资源文件(如images/logo.png)路径正确,打包后能被exe访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 15:04:54