簡體   English   中英

Python py2exe窗口顯示(tkinter)

[英]Python py2exe window showing (tkinter)

我正在嘗試用py2exe創建一個exe。 該程序使用Tkinter顯示一個類似彈出窗口。 問題是,當我像這樣運行設置時一切正常:

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

但是當我嘗試制作一個單文件時它失敗了:

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

實際上最終的exe運行沒有問題,但它沒有顯示任何窗口。 我已經讀過在Windows 7上bundle_files = 1可能存在問題,但我也嘗試了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有一些問題,但是有關於編譯的問題。 我的腳本已編譯,它不會拋出任何異常,但不會顯示窗口...

我最終遇到了同樣的問題,我的解決方案包括執行以下操作:

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

在您的options = {...}

然后手動復制這兩個DLL

PYTHON_PATH\\DLLs\\ (在我的例子中是C:\\Python27\\DLLs

到exe的位置並嘗試運行它。

dll_excludes和手動復制的替代方法是修補py2exe,以便知道這些文件必須直接放在dist目錄中。

在build_exe.py中,有一個名為py2exe的類,其中包含dll的列表dlls_in_exedir ,必須去那里。 此列表在名為plat_prepare的函數期間設置,您可以將tclXX.dll和tkXX.dll文件添加到其中以確保正確復制它們。

當然,除非你是唯一一個能夠構建它的人,否則你不一定知道需要捆綁哪個Tcl和Tk版本 - 有些人可能自己構建了Python,或者使用較舊的Python和較舊的DLL。 因此,您需要檢查系統實際​​使用的版本。 py2exe實際上已經在不同的地方執行此操作:通過導入內部_tkinter模塊(實際的Tk接口,通常是DLL)並訪問TK_VERSIONTCL_VERSION ,然后您可以使用它來生成和添加正確的文件名。

如果其他人應該構建你的應用程序,你可能不想讓他們修改他們的py2exe安裝,所以這里是你如何從你的setup.py monkeypatch它:

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

如果您只有一個版本,則可以使用via data_file復制文件。 下面是完整的例子:

  • 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", ))
                       )
                    ] 

    , 
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM