cx_Freeze で tkinter を使うコードをビルドすると,
- TK_LIBRARY, TCL_LIBRARY の環境変数がセットされていない
- tk86t.dll tcl86.dll がコピーされない
といった諸々の面倒に出会います.
いろいろなところで解決策が提示されているのですが, アドホックな話が多く, 例えば venv の中できちんと動かすには? といった事例はあまりないように思えます.
ということで取りあえず cx_Freeze 用の setup.py の中で, 上記の 1, 2 を解決するスケルトンです.
(python 3.7 で動作確認)
参考資料は
- https://stackoverflow.com/questions/34939356/python-pygame-exe-build-with-cx-freeze-tcl-library-error
- https://stackoverflow.com/questions/43464355/how-to-find-the-path-of-tcl-tk-library-that-tkinter-is-currently-using
- https://qiita.com/sta/items/b360c5fb61ae2d22b321
import sys
import os
import pathlib
# set {TCL,TK}_LIBRARY environment variable
import tkinter
root = tkinter.Tk()
tcl_library_path = pathlib.Path(root.tk.exprstring('$tcl_library'))
tk_library_path = pathlib.Path(root.tk.exprstring('$tk_library'))
os.environ['TCL_LIBRARY'] = str(tcl_library_path)
os.environ['TK_LIBRARY'] = str(tk_library_path)
# find tk86t.dll and tcl86t.dll
tcltk_search_dll = {'tk86t.dll', 'tcl86t.dll'}
tcltk_found_dll = {}
for p in sys.path:
p = pathlib.Path(p)
for f in p.glob('*'):
if f.is_file():
f_low = f.name.lower()
if f_low in tcltk_search_dll:
tcltk_found_dll[f_low] = str(f)
tcltk_search_dll.remove(f_low)
if not tcltk_search_dll:
break
else:
continue
break
if tcltk_search_dll:
raise 'cannot find tcl/tk DLL. ' + str(tcltk_search_dll)
print('tcl/tk DLL:', tcltk_found_dll)
tcltk_include_files = [(v, 'lib/'+k) for k, v in tcltk_found_dll.items()]
from cx_Freeze import setup, Executable
buildOptions = dict(
packages = [],
excludes = [],
include_files = tcltk_include_files)
base = 'Console'
executables = [
Executable('myprog.py', base=base)
]
setup(name='myproj',
version = '1.0',
description = 'my project',
options = dict(build_exe = buildOptions),
executables = executables)