cx_Freeze Tkinter 应用程序的构建非常有问题
cx_Freeze Build of Tkinter Application Extremely Buggy
我最近使用tkinter
(python版本3.6.1)创建了一个小游戏,并使用cx_Freeze
冻结了它。游戏有四个按钮:撤消按钮、重新启动按钮、"find legal moves" 按钮和 "find best move button"。 "find best move" 按钮使用 shelve
数据库来查找前三圈的最佳着法,并使用递归函数在第四圈及以上的过程中动态遍历着法树。我的代码在不应使用按钮时将其禁用。
我确保在安装脚本中包含必要的 DLL,并且我能够 运行 可执行文件而没有错误。但是,直到第四轮(开始使用递归函数时),其中三个按钮才被禁用,并且该应用程序在许多其他方面都非常错误。但是,当我 运行 解冻版本时,它工作得很好。
老实说,我不知道我需要向你们提供哪些代码片段,因为这个问题让我完全不知所措。我唯一的线索是构建中的 pyc
文件与解冻应用程序的大小不同。我知道这很含糊,但我不知道提供哪些具体细节会有用。如果可能的话,我们将不胜感激。
"Find best move"方法:
def _find_best_move(self):
"""Finds best move possible for current game."""
if len(self.game.moves) <= 3:
with shelve.open("paths") as db:
best_paths = db[str(self.game.moves)]
best_path = choice(best_paths)
else:
self.path_finder(self.game)
best_path = self.path_finder.best_path
best_move = best_path[len(self.game.moves)]
best_move = (__class__._add_offset(best_move[0]), best_move[1])
return best_move
更新按钮状态:
def update_gui(self):
"""Updates GUI to reflect current game conditions."""
legal_moves = self.game.find_legal_moves()
if self.game.moves:
self.undo_btn["state"] = "!disabled"
self.restart_btn["state"] = "!disabled"
self.best_move_btn["state"] = "!disabled"
else:
self.undo_btn["state"] = "disabled"
self.restart_btn["state"] = "disabled"
if legal_moves:
self.show_moves_btn["state"] = "!disabled"
else:
self.show_moves_btn["state"] = "disabled"
if legal_moves and self.game.moves:
self.best_move_btn["state"] = "!disabled"
else:
self.best_move_btn["state"] = "disabled"
我的 __init__
文件:
initpath = os.path.dirname(__file__)
os.chdir(os.path.join(initpath, "data"))
PathFinder
class(动态遍历移动树):
class PathFinder:
"""Provides methods to find move paths that meet various criteria.
Designed to be called after the player makes a move.
"""
_game = None
best_path = None
best_score = None
def __call__(self, game):
"""Call self as function."""
if not game:
self._game = DummyGame()
elif not isinstance(game, DummyGame):
self._game = DummyGame(game)
else:
self._game = game
moves = self._game.moves
self.possible_paths = dict.fromkeys(range(1,9))
root = Node(moves[-1])
self._find_paths(root)
self._find_paths.cache_clear()
found_scores = [score for score in self.possible_paths.keys() if
self.possible_paths[score]]
self.best_score = min(found_scores)
self.best_path = self.possible_paths[self.best_score]
@lru_cache(None)
def _find_paths(self, node):
"""Finds possible paths and records them in 'possible_paths'."""
legal_moves = self._game.find_legal_moves()
if not legal_moves:
score = self._game.peg_count
if not self.possible_paths[score]:
self.possible_paths[score] = self._game.moves.copy()
else:
children = []
for peg in legal_moves:
for move in legal_moves[peg]:
children.append(Node((peg, move)))
for child in children:
self._game.move(*child.data)
self._find_paths(child)
try:
self._game.undo()
except IndexError:
pass
挂钩 class:
class Peg(RawPen):
"""A specialized 'RawPen' that represents a peg."""
def __init__(self, start_point, graphics):
"""Initialize self. See help(type(self)) for accurate signature."""
self.graphics = graphics
self.possible_moves = []
super().__init__(self.graphics.canvas, "circle", _CFG["undobuffersize"],
True)
self.pen(pendown=False, speed=0, outline=2, fillcolor="red",
pencolor="black", stretchfactor=(1.25,1.25))
self.start_point = start_point
self.goto(start_point)
self.ondrag(self._remove)
self.onrelease(self._place)
def _remove(self, x, y):
"""Removes peg from hole if it has moves."""
if self.possible_moves:
self.goto(x,y)
def _place(self, x, y):
"""Places peg in peg hole if legal."""
if self.possible_moves:
target_holes = [tuple(map(add, self.start_point, move)) for move in
self.possible_moves]
distances = [self.distance(hole) for hole in target_holes]
hole_distances = dict(zip(distances, target_holes))
nearest_hole = hole_distances[min(hole_distances)]
if self.distance(nearest_hole) <= 0.45:
self.goto(nearest_hole)
peg = self.graphics._subtract_offset(self.start_point)
move = tuple(map(sub, self.pos(), self.start_point))
move = tuple(map(int, move))
self.graphics.game.move(peg, move)
self.start_point = self.pos()
else:
self.goto(self.start_point)
冻结的应用程序将具有与未冻结的应用程序不同的 __value__
值。你将不得不相应地处理它!这是一个困扰很多人的常见问题。任何假设在文件系统中找到该模块的东西在冻结时都会停止正常工作。另一个问题是模块的动态导入。
documentation 涵盖了这个主题和其他主题,希望对您有所帮助!
我最近使用tkinter
(python版本3.6.1)创建了一个小游戏,并使用cx_Freeze
冻结了它。游戏有四个按钮:撤消按钮、重新启动按钮、"find legal moves" 按钮和 "find best move button"。 "find best move" 按钮使用 shelve
数据库来查找前三圈的最佳着法,并使用递归函数在第四圈及以上的过程中动态遍历着法树。我的代码在不应使用按钮时将其禁用。
我确保在安装脚本中包含必要的 DLL,并且我能够 运行 可执行文件而没有错误。但是,直到第四轮(开始使用递归函数时),其中三个按钮才被禁用,并且该应用程序在许多其他方面都非常错误。但是,当我 运行 解冻版本时,它工作得很好。
老实说,我不知道我需要向你们提供哪些代码片段,因为这个问题让我完全不知所措。我唯一的线索是构建中的 pyc
文件与解冻应用程序的大小不同。我知道这很含糊,但我不知道提供哪些具体细节会有用。如果可能的话,我们将不胜感激。
"Find best move"方法:
def _find_best_move(self):
"""Finds best move possible for current game."""
if len(self.game.moves) <= 3:
with shelve.open("paths") as db:
best_paths = db[str(self.game.moves)]
best_path = choice(best_paths)
else:
self.path_finder(self.game)
best_path = self.path_finder.best_path
best_move = best_path[len(self.game.moves)]
best_move = (__class__._add_offset(best_move[0]), best_move[1])
return best_move
更新按钮状态:
def update_gui(self):
"""Updates GUI to reflect current game conditions."""
legal_moves = self.game.find_legal_moves()
if self.game.moves:
self.undo_btn["state"] = "!disabled"
self.restart_btn["state"] = "!disabled"
self.best_move_btn["state"] = "!disabled"
else:
self.undo_btn["state"] = "disabled"
self.restart_btn["state"] = "disabled"
if legal_moves:
self.show_moves_btn["state"] = "!disabled"
else:
self.show_moves_btn["state"] = "disabled"
if legal_moves and self.game.moves:
self.best_move_btn["state"] = "!disabled"
else:
self.best_move_btn["state"] = "disabled"
我的 __init__
文件:
initpath = os.path.dirname(__file__)
os.chdir(os.path.join(initpath, "data"))
PathFinder
class(动态遍历移动树):
class PathFinder:
"""Provides methods to find move paths that meet various criteria.
Designed to be called after the player makes a move.
"""
_game = None
best_path = None
best_score = None
def __call__(self, game):
"""Call self as function."""
if not game:
self._game = DummyGame()
elif not isinstance(game, DummyGame):
self._game = DummyGame(game)
else:
self._game = game
moves = self._game.moves
self.possible_paths = dict.fromkeys(range(1,9))
root = Node(moves[-1])
self._find_paths(root)
self._find_paths.cache_clear()
found_scores = [score for score in self.possible_paths.keys() if
self.possible_paths[score]]
self.best_score = min(found_scores)
self.best_path = self.possible_paths[self.best_score]
@lru_cache(None)
def _find_paths(self, node):
"""Finds possible paths and records them in 'possible_paths'."""
legal_moves = self._game.find_legal_moves()
if not legal_moves:
score = self._game.peg_count
if not self.possible_paths[score]:
self.possible_paths[score] = self._game.moves.copy()
else:
children = []
for peg in legal_moves:
for move in legal_moves[peg]:
children.append(Node((peg, move)))
for child in children:
self._game.move(*child.data)
self._find_paths(child)
try:
self._game.undo()
except IndexError:
pass
挂钩 class:
class Peg(RawPen):
"""A specialized 'RawPen' that represents a peg."""
def __init__(self, start_point, graphics):
"""Initialize self. See help(type(self)) for accurate signature."""
self.graphics = graphics
self.possible_moves = []
super().__init__(self.graphics.canvas, "circle", _CFG["undobuffersize"],
True)
self.pen(pendown=False, speed=0, outline=2, fillcolor="red",
pencolor="black", stretchfactor=(1.25,1.25))
self.start_point = start_point
self.goto(start_point)
self.ondrag(self._remove)
self.onrelease(self._place)
def _remove(self, x, y):
"""Removes peg from hole if it has moves."""
if self.possible_moves:
self.goto(x,y)
def _place(self, x, y):
"""Places peg in peg hole if legal."""
if self.possible_moves:
target_holes = [tuple(map(add, self.start_point, move)) for move in
self.possible_moves]
distances = [self.distance(hole) for hole in target_holes]
hole_distances = dict(zip(distances, target_holes))
nearest_hole = hole_distances[min(hole_distances)]
if self.distance(nearest_hole) <= 0.45:
self.goto(nearest_hole)
peg = self.graphics._subtract_offset(self.start_point)
move = tuple(map(sub, self.pos(), self.start_point))
move = tuple(map(int, move))
self.graphics.game.move(peg, move)
self.start_point = self.pos()
else:
self.goto(self.start_point)
冻结的应用程序将具有与未冻结的应用程序不同的 __value__
值。你将不得不相应地处理它!这是一个困扰很多人的常见问题。任何假设在文件系统中找到该模块的东西在冻结时都会停止正常工作。另一个问题是模块的动态导入。
documentation 涵盖了这个主题和其他主题,希望对您有所帮助!