Nuitka --onefile + Tkinter 报错:找不到 init.tcl 的一次排查记录

TL;DR:当 TMP​ 指向 C:\Windows\TEMP​ 时,Nuitka 的 --onefile​ 解包到系统临时目录,Tkinter 启动找不到 init.tcl​,同时还可能触发 ld.exe: cannot find @C:\Windows\TEMP\...​ 的链接错误。 TMP改到用户临时目录(如与 %TEMP%一致)即可解决。


故障环境

  • 最小复现代码ui.py

    import tkinter as tk
    
    root = tk.Tk()
    tk.Label(root, text="Hello, Tkinter!").pack()
    root.mainloop()
    
  • Nuitka(2.8.4)、Conda 全新python=3.10、MinGW64。

注:Nuitka 官方支持 Tkinter


故障描述

# 正常
nuitka --standalone --enable-plugin=tk-inter ui.py

# 异常(--onefile)
nuitka --standalone --enable-plugin=tk-inter --onefile ui.py

运行 --onefile​ 产物后运行出现错误:

Traceback (most recent call last):
  File "C:\Windows\TEMP\onefile_229924_134063974799743111\test.py", line 4, in <module>
    root = tk.Tk()

  File "C:\Windows\TEMP\onefile_229924_134063974799743111\tkinter\__init__.py", line 2346, in __init__
_tkinter.TclError: Can't find a usable init.tcl in the following directories:
    {C:\Windows\TEMP\onefile_229924_134063974799743111\tcl} C:/Windows/TEMP/onefile_229924_134063974799743111/tcl8.6 C:/Windows/TEMP/lib/tcl8.6 C:/Users/flt/Desktop/tools/lib/tcl8.6 C:/Users/flt/Desktop/lib/tcl8.6 C:/Users/flt/Desktop/tools/library C:/Users/flt/Desktop/library C:/Users/flt/Desktop/tcl8.6.15/library C:/Users/flt/tcl8.6.15/library

This probably means that Tcl wasn't installed properly.

同时注意到在 --mingw64​ 链接阶段还遇到:

Nuitka-Scons: Backend C linking with 6 files (no progress information available for this stage).
.../ld.exe: cannot find @C:\Windows\TEMP\cc67JEzH: Invalid argument
.../ld.exe: cannot find @C:\Windows\TEMP\cc4EhsFs: Invalid argument
collect2.exe: error: ld returned 1 exit status

scons: *** [...\test.dll] Error 1
FATAL: Failed unexpectedly in Scons C backend compilation.
Nuitka:WARNING:     Complex topic! More information can be found at https://nuitka.net/info/scons-backend-failure.html
Nuitka-Reports: Compilation crash report written to file 'nuitka-crash-report.xml'.

排查过程

  1. 确认 Nuitka 与 Tkinter 的兼容性没问题:升级 Nuitka,并在 Conda 全新环境中多次测试 --standalone​,均正常。

  2. 对比两类报错,共同点均指向 C:\Windows\TEMP\... ​。

  3. 检查环境变量,发现 TMP指向 C:\Windows\TEMP​。

  4. 在当前会话里尝试:

    set TMP=%TEMP%
    

    重新编译/运行后,问题消失,确认根因与 TMP​ 所在目录有关。


解决方案

在用户环境变量中显式指定TMP​与TEMP​相同。