KeyError: 'TCL_Library', когда я использую cx_Freeze
Когда я использую cx_Freeze
Я получаю ключевую ошибку KeyError: 'TCL_Library'
при создании моей программы Pygame. Почему я получаю это и как мне это исправить?
Мой setup.py ниже:
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")],
)
5 ответов
Вы можете обойти эту ошибку, установив переменные среды вручную:
set TCL_LIBRARY=C:\Program Files\Python35-32\tcl\tcl8.6
set TK_LIBRARY=C:\Program Files\Python35-32\tcl\tk8.6
Вы также можете сделать это в setup.py
сценарий:
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([..])
Но я обнаружил, что на самом деле запуск программы не работает. В списке рассылки cx_freeze было упомянуто:
Я уже изучил это, и нет, это не просто перекомпиляция - или это было бы уже сделано!:-)
Он находится в стадии разработки и, похоже, потребует немного усилий. Некоторый код для обработки таких вещей, как модули расширения внутри пакетов, падает - и это может быть лучше решено путем удаления этого кода и принудительного размещения пакета вне zip-файла (еще один запрос на извлечение, который необходимо принять). У меня должно быть время на следующей неделе и следующей неделе, чтобы разобраться в этом подробнее. Так что все работает хорошо, я должен выпустить новую версию cx_Freeze до конца года.
Но, возможно, вам повезет больше... Вот отчет об ошибке.
Вместо установки переменных среды с использованием конкретных абсолютных путей установки, таких как C:\\LOCAL_TO_PYTHON\\...
Вы также можете получить необходимые пути динамически, используя __file__
атрибут стандартного пакета Python, как 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')
После этого исправления будет создан исполняемый файл, но вы, вероятно, получите "DLL not found error" при попытке его выполнить - по крайней мере, с Python 3.5.3 и cx_Freeze 5.0.1 в Windows 10.
Когда вы добавите следующие параметры, необходимые DLL-файлы будут автоматически скопированы из каталога Python-Installation в выходные данные сборки cx-Freeze, и вы сможете запустить приложение Tcl/Tk:
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,
# ...
)
Просто поместите это перед установкой в 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"
И запустите это:
python setup.py bdist_msi
Это работало нормально для меня.
Если вы получаете следующую ошибку с 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'
Просто создать LOCAL_TO_PYTHON
режиссёр C:\
затем создать Python35-32
реж внутри него. Теперь скопируйте tcl
реж из существующих Python36
реж (в C:\
) в Python35-32
,
Тогда все работает нормально.
Если вы получаете следующую ошибку с Python 3.6:
копирование C:\LOCAL_TO_PYTHON\Python35-32\tcl\tcl8.6
-> build\exe.win-amd64-3.6\tcl
ошибка: [Errno 2] No such file or directory: 'C:\\LOCAL_TO_PYTHON\\Python35-32\\tcl\\tcl8.6'
Просто создайте каталог LOCAL_TO_PYTHON в C:\, а затем создайте каталог Python35-32 внутри него. Теперь скопируйте tcl dir из существующего Python36 dir (в C:) в Python35-32.
Тогда все работает нормально.
** Я сделал эти шаги и создал файл.exe в директории сборки, но если я пытаюсь нажать кнопку "app", не ждите на экране мгновенно, мои коды здесь **
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()
Ответ Д.Л. Мюллера необходимо изменить для версии cx_Freeze 5.1.1 или 5.1.0. В этих версиях cx_Freeze пакеты замораживаются в подкаталоге lib
каталога сборки. Библиотеки TCL и TK также должны быть перемещены туда. Это может быть достигнуто путем передачи кортежа (source, destination)
к соответствующей записи include_files
опция списка (см. документацию cx_Freeze).
В целом setup.py
Скрипт необходимо изменить следующим образом:
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,
# ...
)
Начальная проблема KeyError:
Это работало для меня с Python 3.7 на 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")]
)
Теперь cx_Freeze работает: