Skip to content

Commit 62ed708

Browse files
committed
docs: document tcl/tk support files quirks
This is useful documentation to have. This should hopefully address all the questions in #68.
1 parent 0ae5aa5 commit 62ed708

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

docs/quirks.rst

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
Behavior Quirks
55
===============
66

7+
.. _quirk_shebangs:
8+
79
Bad Shebangs in Python Scripts
810
==============================
911

@@ -23,6 +25,8 @@ Alternatively, you can sometimes execute ``python3 -m <module>``
2325
to get equivalent functionality to what the installed script would
2426
do. e.g. to run pip, ``python3 -m pip ...``.
2527

28+
.. _quirk_backspace_key:
29+
2630
Backscape Key Doesn't work in Python REPL
2731
=========================================
2832

@@ -73,3 +77,85 @@ If running macOS::
7377
e.g.::
7478

7579
$ TERMINFO_DIRS=/etc/terminfo:/lib/terminfo:/usr/share/terminfo install/bin/python3.9
80+
81+
.. _quirk_tcl:
82+
83+
Tcl/tk Support Files
84+
====================
85+
86+
Python functionality using tcl/tk (such as the ``tkinter`` or ``turtle``
87+
modules) requires loading ``.tcl`` support files from the filesystem.
88+
If these support files cannot be found, you'll get an error like
89+
``_tkinter.TclError: Can't find a usable init.tcl in the following
90+
directories:``.
91+
92+
Distributions produced from this project contain tcl/tk support files.
93+
The paths to these files in the extracted distribution are advertised
94+
in the ``PYTHON.json`` file.
95+
96+
When tcl is initialized by Python, Python and tcl attempt to locate the
97+
``.tcl`` support files. If the ``tcl<X.Y>/init.tcl`` file cannot be found,
98+
an error occurs.
99+
100+
But the mechanism for finding the ``.tcl`` files varies by platform.
101+
102+
On all platforms, if the ``TCL_LIBRARY`` environment variable is set,
103+
it will be used to locate the ``.tcl`` support files. This environment
104+
variable is processed by tcl itself and is documented at
105+
https://wiki.tcl-lang.org/page/TCL_LIBRARY.
106+
107+
On Windows, CPython will attempt to locate the ``.tcl`` support files in
108+
well-defined directories. The C code performs the equivalent of the
109+
following:
110+
111+
.. code-block:: python
112+
113+
import os
114+
import sys
115+
116+
def get_tcl_path():
117+
# e.g. sys.prefix/tcl/tcl8.6
118+
p = os.path.join(sys.prefix, "tcl", "tcl<X.Y>")
119+
if os.path.exists(p):
120+
return p
121+
122+
return None
123+
124+
If Python's code can find the support files in the well-defined location,
125+
it calls into the tcl C API and defines the ``tcl_library`` variable to the
126+
found path.
127+
128+
The most robust way to ensure Python/tcl can find the ``.tcl`` support files
129+
is to define ``TCL_LIBRARY`` to the path to the ``.tcl`` files present in
130+
the extracted Python distribution. It is possible to define this environment
131+
variable from within Python. But it must be done before running any Python
132+
code in the ``tkinter`` module. The following example should work on Linux
133+
and macOS distributions:
134+
135+
.. code-block:: python
136+
137+
import os
138+
import sys
139+
140+
os.environ["TCL_LIBRARY"] = os.path.join(os.path.dirname(sys.executable), "..", "lib", "tcl8.6")
141+
142+
import turtle
143+
144+
If you don't set ``TCL_LIBRARY`` on Linux and macOS, the default search
145+
mechanics implemented by Tcl are used. These may pick up ``.tcl`` files from
146+
a location outside the Python distribution. This may *just work*. This may
147+
fail fast. Or it could result in undefined behavior. For best results,
148+
forcefully point Tcl at the ``.tcl`` files from the Python distribution
149+
produced by this project.
150+
151+
On Windows, explicitly setting ``TCL_LIBRARY`` is not required as the
152+
default install layout of this project's Python distributions allows CPython's
153+
filesystem probing code to find the ``.tcl`` files. As long as the
154+
files from ``python/install/tcl`` are present (in a ``tcl`` directory
155+
under the directory where the ``python.exe`` is), things should *just work*.
156+
157+
For reference, PyOxidizer's approach to this problem is to copy all the
158+
``.tcl`` files from the Python distribution into an install location. At
159+
run time, the ``TCL_LIBRARY`` environment variable is set from within
160+
the process before the Python interpreter is initialized. This ensures the
161+
``.tcl`` files from the Python distribution are used.

0 commit comments

Comments
 (0)