这个简单的代码运行得非常好:
import wx
app = wx.App(0)
frame = wx.Frame(None)
test = wx.ProgressDialog('Test', 'Test', maximum = 20, parent = frame, style = wx.PD_CAN_ABORT)
app.MainLoop()
但是,在使用py2exe
...
from distutils.core import setup
import py2exe
setup(script_args = ['py2exe'], windows=[{'script':'progressdlgprobblem.py'}],
options = {'py2exe': {'compressed':1,'bundle_files': 1}}, zipfile = None)
...然后.exe
文件崩溃。
这次崩溃的原因是什么? wx.ProgressDialog
是否需要一些特定的附加元素才能与py2exe
一起使用?
附录1 :当我删除style = wx.PD_CAN_ABORT
时,不再有崩溃。崩溃如何来自style
?
但是,当从.exe
启动时,样式是XP风格的:
与我从.py
(没有py2exe)启动时获得的样式不同:
附录2 :当我删除'bundle_files': 1
时,不再发生崩溃。
但我想将这个捆绑只保留在一个文件中! 如何捆绑到单个.exe文件中导致此次崩溃?
附录3 :使用wx.Python 3.0.1.0b而不是3.0.0.0解决问题的很大一部分(很快就会有更多细节)。
答案 0 :(得分:2)
py2exe(0.6.9)已经过时,如果没有一些额外的更改,它们就无法处理更新的Windows版本。具体来说,它默认包含一些永远不应捆绑的Windows系统DLL。为防止这种情况,请尝试按如下方式更改设置脚本:
from distutils.core import setup
import py2exe
# Exclude system DLLs
origIsSystemDLL = py2exe.build_exe.isSystemDLL
def isSystemDLL(pathname):
if os.path.basename(pathname).lower() in ("gdiplus.dll",
"mfc90.dll"):
return 0
if os.path.basename(pathname).lower() in ("powrprof.dll", ) or \
os.path.basename(pathname).lower().startswith("api-ms-win-"):
return 1
return origIsSystemDLL(pathname)
py2exe.build_exe.isSystemDLL = isSystemDLL
# Add the MS VC9 CRT and common controls manifest as resource to the exe
manifest = '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="0.0.0.0"
processorArchitecture="x86"
name="Enter program name here"
type="win32"
/>
<description>Enter program description here</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="x86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.VC90.CRT"
version="9.0.21022.8"
processorArchitecture="x86"
publicKeyToken="1fc8b3b9a1e18e3b"
/>
</dependentAssembly>
</dependency>
</assembly>
'''
setup(script_args=['py2exe'],
windows=[{'script': 'progressdlgprobblem.py',
'other_resources': [(24, 1, manifest)]}],
options = {'py2exe': {'compressed': 1,
'dll_excludes': ['iertutil.dll',
'MPR.dll',
'msvcm90.dll',
'msvcp90.dll',
'msvcr90.dll',
'mswsock.dll',
'urlmon.dll',
'w9xpopen.exe'],
'bundle_files': 1}},
zipfile=None)
为获得最佳互操作性,您还需要从C:\ Windows \ winsxs \ x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.21022复制Microsoft.VC90.CRT.manifest,msvcm90.dll,msvcp90.dll和msvcr90.dll。 8_none_bcb86ed6ac711f91(目录名可能略有不同,但正确的版本9.0.21022.8很重要)到你的exe目录,这样用户就不需要自己安装正确版本的MS VC9 CRT了。
除此之外,您可以尝试PyInstaller,它会自动处理程序集依赖项并默认排除系统DLL。
答案 1 :(得分:1)
ProgressDialog
示例存在问题并添加了进度和清理,但其他方面没有变化。
# -*- coding: utf-8 -*-
import wx
app = wx.App(0)
frame = wx.Frame(None)
max_count = 8
dlg = wx.ProgressDialog('Test caption', 'Test text', maximum = max_count, parent = frame, style = wx.PD_CAN_ABORT)
keepGoing = True # progress routine from wxPython demo
count = 0
while keepGoing and count < max_count:
count += 1
wx.MilliSleep(125)
wx.Yield()
(keepGoing, skip) = dlg.Update(count, 'progress: {0} %'.format(count * 100.0/max_count))
dlg.Destroy() # proper cleanup otherwise process has to be killed
frame.Destroy()
app.MainLoop()
冻结py2exe
是一个痛苦的屁股,但提供恕我直言仍然很好的Windows平台的结果。大多数设置都是尝试错误的。在wxPython wiki中,有一个很好的描述/解释如何管理SxS程序集和清单。
# -*- coding: utf-8 -*-
"""manifest fixes NT-theming and including MSVC runtime issue"""
"""
# Recipe from
http://wiki.wxpython.org/Py2exe%20with%20Python2.6
"""
manifest = """
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="5.0.0.0"
processorArchitecture="x86"
name="%(prog)s"
type="win32"
/>
<description>%(prog)s</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="asInvoker"
uiAccess="false">
</requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.VC90.CRT"
version="9.0.21022.8"
processorArchitecture="x86"
publicKeyToken="1fc8b3b9a1e18e3b">
</assemblyIdentity>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
"""
from distutils.core import setup
import py2exe
dll_excludes = [
'w9xpopen.exe',
'MSVCP90.dll' # reason see link to wxPython-wiki above
]
setup(script_args = ['py2exe'], windows=[{'script':'progressdlg.py',#
"other_resources": [(24, 1, manifest)]}], # manifest added
options = {'py2exe': {'compressed':1,'bundle_files': 1, 'dll_excludes': dll_excludes,
}}, zipfile = None)
至少在我的机器上(WinXP 7 + wxPython 2.9.5.0),这个设置(python setup.py py2exe
)会产生:
.EXE
该示例至少可以在您的计算机上运行(已安装MSCV
运行时)。有关排除的更完整列表,请参阅[wxPython-users] https://groups.google.com/forum/#!topic/wxpython-users/vrd-0cpiH1E
中的并行线程。
esky
库已针对已包含的此怪癖进行了修复,并为wx
提供了实时更新 - 应用,但您可能会或可能不会喜欢它正在设置的不同项目结构。
侧注:我无法在wxPython 2.9.5.0上重现你的崩溃(即使没有程序集)。在Win8机器上使用3.0.0.0冻结时,我在XP上崩溃了,但根据Robin(见https://groups.google.com/forum/#!topic/wxpython-users/8OeBfxTC9Xo
),这应该在3.0.1中解决。
旁注2:这似乎与wxPython 3.0.0.0(经典)有关。在我的XP机器上,即使没有冻结,这个例子也会崩溃。如果升级到wxPython 3.0.1 (phoenix),那么它再次起作用(解冻和py2exe)。冻结的单个文件EXE
在Windows8,64位和WinXP上以正确的主题运行时没有问题。