【问题标题】:Python py2exe window showing (tkinter)Python py2exe 窗口显示(tkinter)
【发布时间】:2013-01-28 16:27:43
【问题描述】:

我正在尝试通过 py2exe 制作一个 exe。该程序正在使用 Tkinter 显示一个类似弹出的窗口。问题是,当我像这样运行设置时一切正常:

setup(windows = [{'script': "msg.py"}], zipfile = None)

但是当我尝试制作一个单一文件的 exe 时它失败了:

setup(windows = [{'script': "msg.py"}], zipfile = None, options = {'py2exe': {'bundle_files': 1, 'compressed': True}})

实际上最终的 exe 运行没有问题,但它不显示任何窗口。我已经读过 bundle_files=1 在 Windows 7 上可能存在问题,但我也尝试过 bundle_files=2 具有相同的效果。 这是我的 msg.py 脚本:

from win32gui import FindWindow, SetForegroundWindow
from Image import open as iopen
from ImageTk import PhotoImage
from Tkinter import Tk, Label
from threading import Timer
from subprocess import Popen
import os

def Thread(t, fun, arg=None):
    if arg<>None: x = Timer(t, fun, arg)
    else: x = Timer(t, fun)
    x.daemon = True
    x.start()

def NewMessage():
    global root
    if not os.path.exists('dane/MSG'):
        open('dane/MSG', 'w').write('')
        root = Tk()
        img = PhotoImage(iopen("incl/nowa.png"))
        label = Label(root, image=img)
        label.image = img
        label.bind("<Button-1>", Click)
        label.pack()
        root.geometry('-0-40')
        root.wm_attributes("-topmost", 1)
        root.overrideredirect(1)
        root.mainloop()

def Click(event):
    global root, exit
    root.destroy()
    os.remove('dane/MSG')
    OpenApp()
    exit = True

def OpenApp():
    hwnd = FindWindow(None, 'My program name')
    if hwnd: SetForegroundWindow(hwnd)
    else: Popen('app.exe')

root, exit = None, False
NewMessage()

有什么想法吗?我读过 Tkinter 存在一些问题,但有一些关于编译的问题。我的脚本已编译,它不会抛出任何异常,但不显示窗口...

【问题讨论】:

    标签: python tkinter py2exe


    【解决方案1】:

    我最终遇到了同样的问题,我的解决方案涉及执行以下操作:

    添加 "dll_excludes": ["tcl85.dll", "tk85.dll"],

    在你的options = {...}

    然后从

    手动复制这两个 DLL

    PYTHON_PATH\DLLs\(在我的情况下为C:\Python27\DLLs

    到你的 exe 的位置并尝试运行它。

    【讨论】:

      【解决方案2】:

      dll_excludes 和手动复制的替代方法是修补 py2exe 以知道这些文件必须直接放在 dist 目录中。

      在 build_exe.py 中,有一个名为 py2exe 的类,其中包含一个列表 dlls_in_exedir 用于必须去那里的 dll。此列表是在名为plat_prepare 的函数期间设置的,您可以将 tclXX.dll 和 tkXX.dll 文件添加到其中以确保它们被正确复制。

      当然,除非你是唯一一个会构建这个的人,否则你不一定知道需要捆绑哪个 Tcl 和 Tk 版本 - 有人可能自己构建了 Python,或者正在使用旧的 Python较旧的 DLL。因此,您需要检查系统实际​​使用的版本。 py2exe 实际上已经在不同的地方执行此操作:通过导入内部 _tkinter 模块(实际的 Tk 接口,通常是 DLL)并访问 TK_VERSIONTCL_VERSION,然后您可以使用它们来生成和添加正确的文件名.

      如果其他人应该构建您的应用程序,您可能不想让他们修改他们的 py2exe 安装,因此您可以从 setup.py 中对其进行猴子补丁:

      import py2exe
      py2exe.build_exe.py2exe.old_prepare = py2exe.build_exe.py2exe.plat_prepare
      def new_prep(self):
        self.old_prepare()
        from _tkinter import TK_VERSION, TCL_VERSION
        self.dlls_in_exedir.append('tcl{0}.dll'.format(TCL_VERSION.replace('.','')))
        self.dlls_in_exedir.append('tk{0}.dll'.format(TK_VERSION.replace('.','')))
      py2exe.build_exe.py2exe.plat_prepare = new_prep
      

      这甚至适用于 Windows 7 上的 bundle_files=1

      【讨论】:

        【解决方案3】:

        如果你只有一个版本,你可以复制文件 通过数据文件。下面是一个完整的例子:

        • WinXP
        • Python2.7.6
        • tk8.5
        • tcl8.5
        • tix8.4.3
        • py2exe 0.6.9

        foo.py:

        # -*- coding: iso-8859-1 -*-
        import Tkinter
        """
        sets TCL_LIBRARY, TIX_LIBRARY and TK_LIBRARY - see installation Lib\lib-tk\FixTk.py
        """
        Tkinter._test()
        

        Setup.py:

        # -*- coding: iso-8859-1 -*-
        from distutils.core import setup
        import py2exe
        import sys
        import os
        import os.path
        sys.argv.append ('py2exe')
        setup (
            options    = 
                {'py2exe': 
                    { "bundle_files" : 1    # 3 = don't bundle (default) 
                                             # 2 = bundle everything but the Python interpreter 
                                             # 1 = bundle everything, including the Python interpreter
                    , "compressed"   : False  # (boolean) create a compressed zipfile
                    , "unbuffered"   : False  # if true, use unbuffered binary stdout and stderr
                    , "includes"     : 
                        [ "Tkinter", "Tkconstants"
        
                        ]
                    , "excludes"      : ["tcl", ]
                    , "optimize"     : 0  #-O
                    , "packages"     : 
                        [ 
                        ]
                    , "dist_dir"     : "foo"
                    , "dll_excludes": ["tcl85.dll", "tk85.dll"]
                    ,               
                    }
                }
            , windows    = 
                ["foo.py"
                ]
            , zipfile    = None
            # the syntax for data files is a list of tuples with (dest_dir, [sourcefiles])
            # if only [sourcefiles] then they are copied to dist_dir 
            , data_files = [   os.path.join (sys.prefix, "DLLs", f) 
                           for f in os.listdir (os.path.join (sys.prefix, "DLLs")) 
                           if  (   f.lower ().startswith (("tcl", "tk")) 
                               and f.lower ().endswith ((".dll", ))
                               )
                            ] 
        
            , 
        )
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-04-13
          • 1970-01-01
          • 2018-01-08
          • 2014-03-25
          • 1970-01-01
          • 2019-01-02
          相关资源
          最近更新 更多