https://github.com/python/cpython/commit/c4eb3adbb42d781e2ad35bee5621f1c621c6767b
commit: c4eb3adbb42d781e2ad35bee5621f1c621c6767b
branch: main
author: Jonathan J. Helmus <[email protected]>
committer: zooba <[email protected]>
date: 2026-06-19T14:23:01Z
summary:
gh-150836: Mount embedded Tk ZIP in _tkinter on Windows (GH-151562)
Tcl/Tk 9 may embed the Tk script library in the Tk DLL on Windows. This
embedded library is not found by Tcl by default.
Mount the loaded Tk DLL as a zipfs archive before calling Tk_Init(), so Tk can
find its embedded tk_library using its existing library discovery logic.
Preserve Tk_Init()'s normal path if the library is not embedded.
files:
A Misc/NEWS.d/next/Windows/2026-06-04-18-53-18.gh-issue-150836.Wci7bZ.rst
M Modules/_tkinter.c
M Modules/tkappinit.c
M Modules/tkinter.h
diff --git
a/Misc/NEWS.d/next/Windows/2026-06-04-18-53-18.gh-issue-150836.Wci7bZ.rst
b/Misc/NEWS.d/next/Windows/2026-06-04-18-53-18.gh-issue-150836.Wci7bZ.rst
new file mode 100644
index 000000000000000..6497b7927db7da3
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2026-06-04-18-53-18.gh-issue-150836.Wci7bZ.rst
@@ -0,0 +1 @@
+Make installed tkinter work with Tcl/Tk 9 builds that embed the Tk script
library in the Tk DLL on Windows.
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 6eca98a3c8033fa..1deff4ed44684cd 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -53,6 +53,10 @@ Copyright (C) 1994 Steen Lumholt.
# include <tk.h>
#endif
+#if defined(MS_WINDOWS) && TK_MAJOR_VERSION >= 9
+# include <tkPlatDecls.h>
+#endif
+
#include "tkinter.h"
#if TK_HEX_VERSION < 0x0805020c
@@ -175,6 +179,57 @@ _get_tcl_lib_path(void)
}
#endif /* MS_WINDOWS */
+#if defined(MS_WINDOWS) && TK_MAJOR_VERSION >= 9
+static void
+mount_tk_dll_zip(void)
+{
+ HINSTANCE tk_module = Tk_GetHINSTANCE();
+ wchar_t *tk_path = NULL;
+ DWORD path_len = 0;
+ for (DWORD buffer_len = 256;
+ tk_path == NULL && buffer_len < (1024 * 1024);
+ buffer_len *= 2)
+ {
+ tk_path = (wchar_t *)PyMem_RawMalloc(
+ buffer_len * sizeof(*tk_path));
+ if (tk_path != NULL) {
+ path_len = GetModuleFileNameW(tk_module, tk_path, buffer_len);
+ if (path_len == buffer_len) {
+ PyMem_RawFree(tk_path);
+ tk_path = NULL;
+ }
+ }
+ }
+
+ if (tk_path == NULL || path_len == 0) {
+ PyMem_RawFree(tk_path);
+ return;
+ }
+
+ Tcl_DString utf8_path;
+
+ Tcl_DStringInit(&utf8_path);
+ Tcl_WCharToUtfDString(tk_path, path_len, &utf8_path);
+ /* Failure is harmless if the DLL has no embedded ZIP or if another
+ interpreter has already mounted it. */
+ (void) TclZipfs_Mount(NULL, Tcl_DStringValue(&utf8_path),
+ "//zipfs:/lib/tk", NULL);
+ Tcl_DStringFree(&utf8_path);
+ PyMem_RawFree(tk_path);
+}
+#endif
+
+int
+Tkinter_TkInit(Tcl_Interp *interp)
+{
+#if defined(MS_WINDOWS) && TK_MAJOR_VERSION >= 9
+ /* Tcl/Tk 9 may embed the tk_library in the Tk DLL which tcl_findLibrary
+ does not search. Mount the DLL using Zipfs if possible. */
+ mount_tk_dll_zip();
+#endif
+ return Tk_Init(interp);
+}
+
/* The threading situation is complicated. Tcl is not thread-safe, except
when configured with --enable-threads.
@@ -544,7 +599,7 @@ Tcl_AppInit(Tcl_Interp *interp)
return TCL_OK;
}
- if (Tk_Init(interp) == TCL_ERROR) {
+ if (Tkinter_TkInit(interp) == TCL_ERROR) {
PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
return TCL_ERROR;
}
@@ -2988,7 +3043,7 @@ _tkinter_tkapp_loadtk_impl(TkappObject *self)
return NULL;
}
if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
- if (Tk_Init(interp) == TCL_ERROR) {
+ if (Tkinter_TkInit(interp) == TCL_ERROR) {
Tkinter_Error(self);
return NULL;
}
diff --git a/Modules/tkappinit.c b/Modules/tkappinit.c
index 4c4081e43a8e3dd..1075ccf24d44877 100644
--- a/Modules/tkappinit.c
+++ b/Modules/tkappinit.c
@@ -37,7 +37,7 @@ Tcl_AppInit(Tcl_Interp *interp)
return TCL_OK;
}
- if (Tk_Init(interp) == TCL_ERROR) {
+ if (Tkinter_TkInit(interp) == TCL_ERROR) {
return TCL_ERROR;
}
diff --git a/Modules/tkinter.h b/Modules/tkinter.h
index 40281c217603318..b73e99b28a40212 100644
--- a/Modules/tkinter.h
+++ b/Modules/tkinter.h
@@ -16,4 +16,6 @@
(TK_RELEASE_LEVEL << 8) | \
(TK_RELEASE_SERIAL << 0))
+int Tkinter_TkInit(Tcl_Interp *interp);
+
#endif /* !TKINTER_H */
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]