47
votes

When I use cx_Freeze I get a keyerror KeyError: 'TCL_Library'while building my pygame program. Why do I get this and how do I fix it?

My setup.py is below:

from cx_Freeze import setup, Executable

setup(
    name = "Snakes and Ladders",
    version = "0.9",
    author = "Adam",
    author_email = "Omitted",
    options = {"build_exe": {"packages":["pygame"],
                         "include_files": ["main.py", "squares.py",
                         "pictures/Base Dice.png", "pictures/Dice 1.png",
                         "pictures/Dice 2.png", "pictures/Dice 3.png",
                         "pictures/Dice 4.png", "pictures/Dice 5.png",
                         "pictures/Dice 6.png"]}},
    executables = [Executable("run.py")],
    )
7

7 Answers

70
votes

You can work around this error by setting the environment variables manually:

set TCL_LIBRARY=C:\Program Files\Python35-32\tcl\tcl8.6
set TK_LIBRARY=C:\Program Files\Python35-32\tcl\tk8.6

You can also do that in the setup.py script:

os.environ['TCL_LIBRARY'] = r'C:\Program Files\Python35-32\tcl\tcl8.6'
os.environ['TK_LIBRARY'] = r'C:\Program Files\Python35-32\tcl\tk8.6'

setup([..])

But I found that actually running the program doesn't work. On the cx_freeze mailinglist it was mentioned:

I have looked into it already and no, it is not just a simple recompile -- or it would have been done already! :-)

It is in progress and it looks like it will take a bit of effort. Some of the code in place to handle things like extension modules inside packages is falling over -- and that may be better solved by dropping that code and forcing the package outside the zip file (another pull request that needs to be absorbed). I should have some time next week and the week following to look into this further. So all things working out well I should put out a new version of cx_Freeze before the end of the year.

But perhaps you have more luck ... Here's the bug report.

36
votes

Instead of setting the environment variables using installation specific absolute paths like C:\\LOCAL_TO_PYTHON\\... you may also derive the necessary paths dynamically using the __file__ attribute of Python standard package like os:

import os.path
PYTHON_INSTALL_DIR = os.path.dirname(os.path.dirname(os.__file__))
os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6')
os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')

After this fix the executable file will be created, but you will probably get a "DLL not found error" when you try to execute it - at least with Python 3.5.3 and cx_Freeze 5.0.1 on Windows 10.

When you add the following options, the necessary DLL-files will be copied automatically from the Python-Installation directory to the build-output of cx-Freeze and you should be able to run your Tcl/Tk application:

options = {
    'build_exe': {
        'include_files':[
            os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tk86t.dll'),
            os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tcl86t.dll'),
         ],
    },
}

# ...

setup(options = options,
      # ...
)
15
votes

Just put this before the setup at setup.py

import os

os.environ['TCL_LIBRARY'] = "C:\\LOCAL_TO_PYTHON\\Python35-32\\tcl\\tcl8.6"
os.environ['TK_LIBRARY'] = "C:\\LOCAL_TO_PYTHON\\Python35-32\\tcl\\tk8.6"

And run it:

python setup.py bdist_msi

This worked fine for me.

6
votes

If you get following error with python 3.6:

copying C:\LOCAL_TO_PYTHON\Python35-32\tcl\tcl8.6 -> build\exe.win-amd64-3.6\tcl
error: [Errno 2] No such file or directory: 'C:\\LOCAL_TO_PYTHON\\Python35-32\\tcl\\tcl8.6'

Simply create LOCAL_TO_PYTHON dir in C:\ then create Python35-32 dir inside it. Now copy tcl dir from existing Python36 dir (in C:\) into Python35-32.

Then it works fine.

0
votes

If you get following error with python 3.6:

copying C:\LOCAL_TO_PYTHON\Python35-32\tcl\tcl8.6 -> build\exe.win-amd64-3.6\tcl error: [Errno 2] No such file or directory: 'C:\\LOCAL_TO_PYTHON\\Python35-32\\tcl\\tcl8.6'

Simply create LOCAL_TO_PYTHON dir in C:\ then create Python35-32 dir inside it. Now copy tcl dir from existing Python36 dir (in C:) into Python35-32.

Then it works fine.

**I did this steps and created a .exe file into the build dir but if ı try to click app dont wait on the screen instantly quick, my codes here **

from tkinter import *
import socket



window=Tk()
window.geometry("400x150")
window.title("IpConfiger")
window.config(background="black")

def goster():
    x=socket.gethostbyname(socket.gethostname())
    label=Label(window,text=x,fg="green",font=("Helvetica",16))
    label.pack()
def information():
    info=Label(window,text="Bu program anlık ip değerini 
    bastırır.",fg="green",font=("Helvetica",16),bg="black")
    info.pack()


information()
tikla=Button(window,text="ip göster",command=goster)

tikla.pack()
0
votes

D. L. Müller's answer need to be modified for cx_Freeze version 5.1.1 or 5.1.0. In these versions of cx_Freeze, packages get frozen into a subdirectory lib of the build directory. The TCL and TK DLLs need to be moved there as well. This can be achieved by passing a tuple (source, destination) to the corresponding entry of the include_files list option (see the cx_Freeze documentation).

Altogether the setup.py script needs to be modified as follows:

import os.path
PYTHON_INSTALL_DIR = os.path.dirname(os.path.dirname(os.__file__))
os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6')
os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')

# ...

options = {
    'build_exe': {
        'include_files':[
            (os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tk86t.dll'), os.path.join('lib', 'tk86t.dll'))
            (os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'tcl86t.dll'), os.path.join('lib', 'tcl86t.dll'))
         ],
    },
}

# ...

setup(options = options,
      # ...
)
0
votes

The initial KeyError problem:

KeyError

This worked for me with python 3.7 on windows 7:

from cx_Freeze import setup, Executable
import os
import sys

where = os.path.dirname(sys.executable)


os.environ['TCL_LIBRARY'] = where+"\\tcl\\tcl8.6"
os.environ['TK_LIBRARY'] = where+"\\tcl\\tk8.6"

build_exe_options = {"include_files": [where+"\\DLLs\\tcl86t.dll", where+"\\DLLs\\tk86t.dll"]}  


setup(
    name = "SudoCool",
    version = "0.1",
    description = "Programme de SUDOKU",
    options={"build_exe": build_exe_options},  
    executables = [Executable("sudoku.py")]
) 

Now cx_Freeze is working: it's working

enter image description here

enter image description here

My application is working: enter image description here