11 KiB
一个 py2exe 教程——构建二进制系列!
原文:https://www.blog.pythonlibrary.org/2010/07/31/a-py2exe-tutorial-build-a-binary-series/
我收到了一个请求,要求我写一篇关于如何使用 py2exe 和 wxPython 创建可执行文件的文章。我决定做一个关于包装的系列。亲爱的读者,我打算介绍一下主要的 Windows 二进制构建实用程序,并向您展示如何使用它们来创建可以分发的二进制文件。一旦这些文章完成,我将展示如何使用 Inno 和 NSIS。首先,我们将讨论如何使用 py2exe,这可能是最流行的 Windows 可执行软件包。
我们开始吧
对于本教程,我们将使用一个不做任何事情的 wxPython 脚本。这是一个虚构的例子,但是我们使用 wx 使它比仅仅做一个控制台“Hello World”程序在视觉上更有趣。还要注意我用的是 py2exe 0.6.9,wxPython 2.8.11.0 和 Python 2.6。运行时,最终产品应该是这样的:
现在我们知道了它的样子,下面来看看代码:
import wx
########################################################################
class DemoPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
labels = ["Name", "Address", "City", "State", "Zip",
"Phone", "Email", "Notes"]
mainSizer = wx.BoxSizer(wx.VERTICAL)
lbl = wx.StaticText(self, label="Please enter your information here:")
lbl.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD))
mainSizer.Add(lbl, 0, wx.ALL, 5)
for lbl in labels:
sizer = self.buildControls(lbl)
mainSizer.Add(sizer, 1, wx.EXPAND)
self.SetSizer(mainSizer)
mainSizer.Layout()
#----------------------------------------------------------------------
def buildControls(self, label):
""""""
sizer = wx.BoxSizer(wx.HORIZONTAL)
size = (80,40)
font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
lbl = wx.StaticText(self, label=label, size=size)
lbl.SetFont(font)
sizer.Add(lbl, 0, wx.ALL|wx.CENTER, 5)
if label != "Notes":
txt = wx.TextCtrl(self, name=label)
else:
txt = wx.TextCtrl(self, style=wx.TE_MULTILINE, name=label)
sizer.Add(txt, 1, wx.ALL, 5)
return sizer
########################################################################
class DemoFrame(wx.Frame):
"""
Frame that holds all other widgets
"""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, wx.ID_ANY,
"Py2Exe Tutorial",
size=(600,400)
)
panel = DemoPanel(self)
self.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = DemoFrame()
app.MainLoop()
这相当简单,所以我让读者自己去解决。这篇文章说的毕竟是 py2exe。
py2exe setup.py 文件
任何 py2exe 脚本的关键是 setup.py 文件。这个文件控制包含或排除什么,压缩和打包多少,等等!下面是我们可以在上面的 wx 脚本中使用的最简单的设置:
from distutils.core import setup
import py2exe
setup(windows=['sampleApp.py'])
如你所见,我们从 distutils.core 导入 setup 方法,然后导入 py2exe 。接下来,我们用一个 windows 关键字参数调用 setup,并向它传递 python 列表对象中主文件的名称。如果您正在创建一个非 GUI 项目,那么您将使用控制台键而不是窗口。要运行它,打开命令提示符并导航到适当的位置。然后输入“python setup.py py2exe”运行它。这是我第一次运行时得到的结果:
看起来 wxPython 需要“MSVCP90.dll ”,而 Windows 找不到它。快速的谷歌搜索产生了共识,我需要“微软 Visual C++ 2008 可再发行软件包”,在这里找到了。我下载了它,安装了它,并再次尝试 py2exe。同样的错误。如果我使用 Visual Studio 来创建一个 C#程序的 exe,这可能会有效。无论如何,诀窍是在硬盘上搜索文件,然后将其复制到 Python 的 DLL 文件夹中,在我的机器上,该文件夹位于以下位置:C:\ Python 26 \ DLL(根据需要在您的机器上进行调整)。一旦 DLL 在正确的位置,setup.py 文件就可以正常运行了。结果被放入“dist”文件夹,该文件夹包含 17 个文件,重 15.3 MB。我双击“sampleApp.exe”文件,看看我闪亮的新二进制文件是否能工作,它确实工作了!在旧版本的 wxPython 中,您可能需要包含一个清单文件来获得正确的外观(即主题),但在 2.8.10 中(我认为)这一点已经解决了,就像过去需要的并行(SxS)程序集清单文件一样。
注意,对于非 wxPython 脚本,您可能仍然需要弄乱 SxS 清单和其中包含的所有环。你可以在 py2exe 教程中了解更多。
创建高级 setup.py 文件
让我们通过创建一个更复杂的 setup.py 文件来看看 py2exe 为我们创建二进制文件提供了哪些其他选项。
from distutils.core import setup
import py2exe
includes = []
excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger',
'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl',
'Tkconstants', 'Tkinter']
packages = []
dll_excludes = ['libgdk-win32-2.0-0.dll', 'libgobject-2.0-0.dll', 'tcl84.dll',
'tk84.dll']
setup(
options = {"py2exe": {"compressed": 2,
"optimize": 2,
"includes": includes,
"excludes": excludes,
"packages": packages,
"dll_excludes": dll_excludes,
"bundle_files": 3,
"dist_dir": "dist",
"xref": False,
"skip_archive": False,
"ascii": False,
"custom_boot_script": '',
}
},
windows=['sampleApp.py']
)
这是相当不言自明的,但无论如何让我们解开它。首先,我们设置几个列表,并将其传递给 set up 函数的 options 参数。
- 包含列表是针对您需要特别包含的特殊模块。有时 py2exe 找不到某些模块,所以您需要在这里手动指定它们。
- 排除列表是从程序中排除哪些模块的列表。在这种情况下,我们不需要 Tkinter,因为我们正在使用 wxPython。这个排除列表是 GUI2Exe 默认排除的内容。
- 包列表是要包含的特定包的列表。还是那句话,有时候 py2exe 就是找不到东西。我以前必须在这里包括 email、PyCrypto 或 lxml。请注意,如果排除列表包含您试图包含在包或包含列表中的内容,py2exe 可能会继续排除它们。
- dll_excludes -排除我们项目中不需要的 dll。
在选项字典中,我们还有一些其他的选项可以查看。 compressed 键告诉 py2exe 是否压缩 zip 文件,如果设置了的话。优化键设置优化级别。零表示没有优化,2 表示最高。 bundle_files 键将 dll 捆绑在 zipfile 或 exe 中。 bundle_files 的有效值为:3 =不捆绑(默认)2 =捆绑除 Python 解释器之外的所有内容 1 =捆绑所有内容,包括 Python 解释器。几年前,当我第一次学习 py2exe 时,我在他们的邮件列表上询问最佳选项是什么,因为我对捆绑选项 1 有疑问。有人告诉我,3 可能是最稳定的。我照着做了,不再有随机的问题,所以这是我目前的建议。如果你不喜欢分发多个文件,把它们压缩或者创建一个安装程序。我在这个列表中使用的另外一个选项是 dist_dir 选项。当我不想覆盖我的主要构建时,我用它来试验不同的构建选项或创建自定义构建。你可以在 py2exe 网站上阅读所有其他选项(包括这里没有列出的选项)。通过将 optimize 设置为 2,我们可以将文件夹的大小减少大约一兆字节。
减少 wxPython 脚本的二进制文件大小
wxPython 邮件列表上有一个关于减小二进制文件大小的主题。我联系了 Steven Sproat,其中的一个人,关于他做了什么,这里的诀窍是:设置“bundle_files”选项为 1,zipfile 为 None。结果在你的 dist 文件夹中会有三个文件:MSVCR71.dll,sampleApp.exe 和 w9xpopen.exe。在我的机器上,该文件夹的大小为 5.94 MB(在 Windows XP 机器上测试)。正如我前面提到的,将 bundle_files 设置为 1 会导致一些用户在运行您的应用程序时遇到问题,但这可能已经在 py2exe 的新版本中得到解决。以下是设置了新选项的 setup.py 文件的外观:
from distutils.core import setup
import py2exe
includes = []
excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger',
'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl',
'Tkconstants', 'Tkinter']
packages = []
dll_excludes = ['libgdk-win32-2.0-0.dll', 'libgobject-2.0-0.dll', 'tcl84.dll',
'tk84.dll']
setup(
options = {"py2exe": {"compressed": 2,
"optimize": 2,
"includes": includes,
"excludes": excludes,
"packages": packages,
"dll_excludes": dll_excludes,
"bundle_files": 1,
"dist_dir": "dist",
"xref": False,
"skip_archive": False,
"ascii": False,
"custom_boot_script": '',
}
},
zipfile = None,
windows=['sampleApp.py']
)
另一种减小文件夹大小的方法是使用压缩程序,这是我的一位读者 ProgMan 指出的。以下是他的结果:
包扎
现在,您已经了解了使用 py2exe 创建二进制文件的基础知识。我希望这对您当前或未来的项目有所帮助。如果有,请在评论中告诉我!
进一步阅读
- py2exe 教程
- 打包 wxPyMail 进行分发
- GUI2Exe
- py2exe 上的 wxPython wiki 页面


