Repository navigation
ensure tcl works within virtualenv #93
Description
Originally reported by Shawn Wheatley at https://bugs.launchpad.net/virtualenv/+bug/449537
Environment:
Tested on Windows XP SP3 and Windows 7
Python 2.6.3
Virtualenv 1.3.4
Within a fresh, just activated VirtualEnv, I get the following error trying to run a simple Tkinter window:
H:\My Documents\pythondev>virtualenv H:\testvirtualenv
New python executable in H:\testvirtualenv\Scripts\python.exe
Installing setuptools...................done.
H:\My Documents\pythondev>H:\testvirtualenv\Scripts\activate.bat
(testvirtualenv) H:\My Documents\pythondev>python
Python 2.6.3 (r263rc1:75186, Oct 2 2009, 20:40:30) [MSC v.1500 32 bit (Intel)]
on win32
Type "help", "copyright", "credits" or "license" for more information.
import Tkinter
Tkinter._test()
Traceback (most recent call last):
File "", line 1, in
File "C:\Python26\Lib\lib-tk\Tkinter.py", line 3749, in _test
root = Tk()
File "C:\Python26\Lib\lib-tk\Tkinter.py", line 1643, in init
self.tk = _tkinter.create(screenName, baseName, className, interactive, want
objects, useTk, sync, use)
_tkinter.TclError: Can't find a usable init.tcl in the following directories:
C:/Python26/lib/tcl8.5 H:/testvirtualenv/lib/tcl8.5 H:/lib/tcl8.5 H:/testvir
tualenv/library H:/library H:/tcl8.5.2/library H:/tcl8.5.2/library
This probably means that Tcl wasn't installed properly.
Shawn Wheatley wrote on 2009-10-13:
Virtualenv does not copy the Tcl library file(s) (or any core C extensions, that I can see) to the new virtualenv, but instead adds a reference to the PYTHONPATH. If I copy the "tcl" folder from C:\Python26\ over to the root of the new Virtualenv, Tkinter.Tk() shows a new window without throwing an exception.
Jannis Leidel wrote on 2009-10-13: #2
Just suspecting here but could you create a virtualenv on the same drive as the system Python (C:)? I have the feeling it could be related to https://bugs.launchpad.net/virtualenv/+bug/352844.
Shawn Wheatley wrote on 2009-10-14:
Same problem when creating an environment on C:
C:\Temp>virtualenv TestTkinterBug
New python executable in TestTkinterBug\Scripts\python.exe
Installing setuptools...................done.
C:\Temp>cd TestTkinterBug
C:\Temp\TestTkinterBug>Scripts\activate.bat
(TestTkinterBug) C:\Temp\TestTkinterBug>python
Python 2.6.3 (r263rc1:75186, Oct 2 2009, 20:40:30) [MSC v.1500 32 bit (Intel)]
on win32
Type "help", "copyright", "credits" or "license" for more information.
import Tkinter
Tkinter._test()
Traceback (most recent call last):
File "", line 1, in
File "C:\Python26\Lib\lib-tk\Tkinter.py", line 3749, in _test
root = Tk()
File "C:\Python26\Lib\lib-tk\Tkinter.py", line 1643, in init
self.tk = _tkinter.create(screenName, baseName, className, interactive, want
objects, useTk, sync, use)
_tkinter.TclError: Can't find a usable init.tcl in the following directories:
C:/Python26/lib/tcl8.5 C:/Temp/TestTkinterBug/lib/tcl8.5 C:/Temp/lib/tcl8.5
C:/Temp/TestTkinterBug/library C:/Temp/library C:/Temp/tcl8.5.2/library C:/tcl8.
5.2/library
This probably means that Tcl wasn't installed properly.
Shawn Wheatley wrote on 2009-10-15:
I've figured out the problem, but wondering if someone could give me a suggestion on a "proper" solution. I dug into the Python source and found that importing Tkinter on win32 causes an import of a module called FixTk:
http://svn.python.org/view/python/tags/r263/Lib/lib-tk/FixTk.py?revision=75184&view=markup
This file checks to see if the folder "tcl" exists in sys.prefix ("C:\python26\tcl"), or if the folder tcltk\lib exists in the parent of sys.prefix ("C:\tcltk\lib"). Once it finds an appropriate folder, it drills in to find the actual Tcl library folder, and sets appropriate environment variables (TCL_LIBRARY, TK_LIBRARY, TIX_LIBRARY). Since virtualenv doesn't copy the first folder to the new location, and the second folder doesn't exist (at least on my system), the rest of the module exits without completion--without setting any environment variables. You can see an example of this in a virtualenv on win32 by doing the following:
import os
os.environ.keys().index('TCL_LIBRARY')
Traceback (most recent call last):
File "", line 1, in
ValueError: list.index(x): x not in list
import Tkinter
os.environ.keys().index('TCL_LIBRARY')
Traceback (most recent call last):
File "", line 1, in
ValueError: list.index(x): x not in list
Compare this with stock Python on win32:
import os
os.environ.keys().index('TCL_LIBRARY')
Traceback (most recent call last):
File "", line 1, in
ValueError: list.index(x): x not in list
import Tkinter
os.environ.keys().index('TCL_LIBRARY')
26
I see a few ways to solve this problem, some more elegant than others:
- virtualenv copies the "tcl" folder on win32 to the target folder
Pros: the least impact on both virtualenv and the environment variables; this will continue to allow Tkinter to function as expected in the system Python.
Cons: feels kind of hacky compared to how virtualenv references the rest of the standard library
- virtualenv performs the functions of FixTk.py and sets the appropriate environment variables in activate.bat
Pros: this change is isolated to a Windows-only file (the batch file) and should also cause minimal "damage" in the case where the *_LIBRARY variables are already set (unless changing these in a batch file affects them system wide, I don't remember how exactly that works)
Cons: depending on how variables are set, this may destroy any system-wide *_LIBRARY variables associated with Tcl.
- something similar to VirtualEnvWrapper, set a post deploy hook that sets the appropriate variables
Pros: no patch to virtualenv (yay!)
Cons: Tkinter support on win32 under virtualenv is still broken, this is a workaround that would need to be applied separately on every fresh install (although I'm sure avid virtualenv users already have some bootstrap scripts they use in this fashion anyway)
I seem to be the only Tkinter/virtualenv user on Windows :) so I'd be happy to work on a patch, but I'd like some suggestions as to the approach.
Ian Bicking wrote on 2009-10-16: Re: [Bug 449537] Re: Tkinter calls fail in fresh VirtualEnv
On Thu, Oct 15, 2009 at 3:30 PM, Shawn Wheatley swheatley@gmail.com wrote:
- virtualenv performs the functions of FixTk.py and sets the
appropriate environment variables in activate.batPros: this change is isolated to a Windows-only file (the batch file) and should also cause minimal "damage" in the case where the *_LIBRARY variables are already set (unless changing these in a batch file affects them system wide, I don't remember how exactly that works)
Cons: depending on how variables are set, this may destroy any system-wide *_LIBRARY variables associated with Tcl.
This seems reasonable to me. I'm not clear if the same problem exists
on other platforms? It doesn't seem to for me.
After thinking a bit, I think the best option to implement this would
be to put the FixTk code into the virtualenv site.py. Then activation
won't be required to get Tkinter to work. The FixTk code would be
modified to use sys.real_prefix in addition to sys.prefix.
Activity
whart222 commentedon Apr 13, 2011
Note that this issue blocks the use of MatPlotLib using a virtual Python environment. IMHO, this makes this ticket a big deal.
I like carljm's suggestion of putting the fix in site.py...
JustinSGray commentedon Aug 15, 2011
it would greatly help me if this was delt with. It is a big problem for using MatplotLib with the standard backend inside a virtual env.
Wietse commentedon Jan 10, 2012
I solved this by setting the following environment variables in my activate script:
$env:TCL_LIBRARY = "C:\Python32\tcl\tcl8.5"
$env:TK_LIBRARY = "C:\Python32\tcl\tk8.5"
geographika commentedon Mar 8, 2012
Thanks Wietse. I took a similar approach by modifying my activate.bat script to include:
set TCL_LIBRARY=C:\Python26\ArcGIS10.0\tcl\tcl8.5
set TK_LIBRARY=C:\Python26\ArcGIS10.0\tcl\tk8.5
mapplotlib is now working in the virtualenv.
thisizkp commentedon Jul 6, 2014
Modified the activate.bat script to include the above commands, and it is working.
I am using virtualenvwrapper-win and I had multiple virtualenvs and should i change the activate.bat in all of them..? or is there any one single specific file that would suffice.?
pfmoore commentedon Jul 7, 2014
@citterio I've added some comments to your PR. I don't use Tk at all myself, so I don't have any direct understanding of the situation, but I can understand the problem if this breaks matplotlib.
rbtcollins commentedon May 22, 2015
Seems like FixTK could be fixed in the std lib itself?
dodgex commentedon Oct 7, 2015
my workarround: copy
tcl8.5andtk8.5to one of the paths mentioned in the error (one of those mentioned below this messageCan't find a usable tk.tcl in the following directories:).WorkAround pypa/virtualenv#93.
VelinGeorgiev commentedon Jan 19, 2016
This is my workaround on Azure:

Go to your web app -> Configure -> app settings and set the env variables. You have to know where the python resides sys.real_prefix.
Fix issue pypa#93 - Tcl doesn't work inside a virtualenv on Windows
techtonik commentedon Apr 5, 2016
PR #888 fixed virtualenv with tcl/tk for me on both Python 2.7 and Python 3.5. Please confirm that it works on your configurations too.
Merge pull request #888 from techtonik/tcltk
8 remaining items
test: mark grid voronoi tests with intermittent tkinter/tcl errors as…
pjm56 commentedon Sep 16, 2022
I have been resurrecting some old virtualenvs today and encountered this problem again.
System is 64-bit Windows 10 and 32-bit Python 2.7.18, using Git Bash (MINGW64)
I can confirm that when I create a virtualenv using virtualenv 16.7.12 (pipped into the system python 2.7), the tcl folder is copied across and my project code successfully runs matplotlib.
I can also confirm that if I upgrade to virtualenv==20.1.0 or higher and try again, then tcl is no longer copied across and my code using matplotlib fails. In those circumstances I can workaround the situation by setting this environment variable:
export TCL_LIBRARY="C:\Program Files (x86)\Python27\tcl\tcl8.5"
I have also tried this using Python 3.10 as my system python, but targeting 2.7.18 for the virtualenv (that is, using option "-p 2.7"). I get the same results. If Python 3.10 has virtualenv==16.7.12 then tcl gets copied across. Any higher version and it does not.
gaborbernat commentedon Nov 21, 2023
PR welcome.
alexchandel commentedon Dec 6, 2024
13 years later, what's the workaround for tkinter + virtualenv ?
gaborbernat commentedon Jan 3, 2025
Same as was 13 years before. Open a PR fixing it, if you want to use it.
feat: Add Tcl/Tkinter support for activation scripts