第40章-PY2Exe

py2exe项目曾经是从Python应用程序创建Windows可执行文件的主要方法。py2exe的常规版本只支持python 2.3-2.7。上列出了一个新版本 PyPI 这也适用于Python3.4。我们将重点讨论Python2.x版本,尽管本章也将与Python3版本一起使用。

您的应用程序有几个选择。您可以创建仅在终端中运行的程序,可以创建桌面图形用户界面(GUI),也可以创建Web应用程序。我们将创建一个非常简单的桌面界面,除了显示用户可以填写的表单之外,它什么都不做。我们将使用wxpython gui工具包来帮助演示Py2Exe如何在不通知的情况下获取包。

创建一个简单的图形用户界面

您将要访问wxpython的网站(www.wxpython.org)并下载与您的python版本匹配的副本。如果您有一个32位的python,请确保您下载了一个32位的wxpython。您不能使用easy-install或pip来安装wxpython,除非您获得了wxpython的出血边缘凤凰版本,所以您必须从wxpython网站或系统的包管理器获取为您的系统预建的副本。我建议至少使用Wxpython 2.9或更高版本。

让我们写一些代码!

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):
        """
        Put the widgets together
        """
        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()

如果运行上面的代码,您应该看到如下内容:

_images/py2exe_wx.jpg

让我们把这个分解一下。我们创建了两个类, DemoPanelDemoFrame .在Wxpython中, wx.Frame 对象是在大多数情况下用来创建实际“窗口”的对象。您添加了一个 wx.Panel 为应用程序提供正确的外观和感觉,并在字段之间添加制表符。面板对象的父对象是框架。框架是顶级小部件,没有父级。该面板包含本例中的所有其他小部件。我们使用sizer来帮助布局小部件。sizer允许开发人员创建小部件,当窗口本身调整大小时,这些小部件将适当调整大小。您也可以使用绝对定位将小部件放置在面板上,这是不推荐的。我们称之为 MainLoop 方法 wx.App 对象以启动事件循环,从而允许wxpython响应鼠标和键盘事件(如单击、键入等)。

现在我们已经准备好学习如何将这个应用程序打包成一个可执行文件了!

注意:我在Windows7上使用python 2.7.3、wxpython2.9.4.0(经典)和py2exe 0.6.9进行了测试。

py2exe setup.py文件

任何py2exe脚本的关键是 setup.py 文件。这个文件控制包含或排除的内容,压缩和捆绑的数量,等等!下面是我们可以与上面的WX脚本一起使用的最简单的设置:

from distutils.core import setup
import py2exe

setup(windows=['sampleApp.py'])

如您所见,我们导入 设置 方法从 distutils.core 然后我们进口 PY2Exe公司 .接下来我们用 windows 关键字参数,并将主文件的名称传递给python list对象。如果您正在创建一个非GUI项目,那么您将使用 慰问 键而不是 windows .要运行此代码段,请将其保存到与wxpython脚本相同的文件夹中,打开命令提示并导航到保存这两个文件的位置。然后键入 python安装.py py2exe 运行它。如果一切顺利,您将看到许多输出以如下方式结束:

_images/py2exe_output.jpg

如果您碰巧使用了python 2.6,您可能会得到一个关于 MSVCP90.dll 找不到。如果您看到这个错误,您可能需要找到 微软Visual C++ 2008可重分配软件包 并安装它使DLL在您的系统上可用。有时,您会创建可执行文件,然后在运行它时,它将无法正确加载。当发生这种情况时,通常会创建一个日志文件,您可以使用它来尝试找出发生了什么。我还找到了一个叫做 依赖性助行器 可以对可执行文件运行,它可以告诉您缺少的非python项(如dlls等)。

我想指出的是 setup.py 文件未显式包含wxpython。这意味着py2exe足够智能,可以自动包含wxpython包。让我们花些时间来学习包含和排除包的更多内容。

创建高级setup.py文件

让我们看看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": 3,
                          "dist_dir": "dist",
                          "xref": False,
                          "skip_archive": False,
                          "ascii": False,
                          "custom_boot_script": '',
                         }
              },
    windows=['sampleApp.py']
    )

这是不言自明的,但我们还是把它拆开吧。首先,我们设置一些列表,并将其传递给设置函数的选项参数。

  • 这个 包括 列表是为您需要特别包括的特殊模块而列出的。有时候Py2Exe找不到某些模块,所以您可以在这里手动指定它们。

  • 这个 排除 list是从程序中排除哪些模块的列表。在这种情况下,我们不需要tkinter,因为我们使用wxpython。此排除列表是gui2exe默认排除的内容。

  • 这个 包装 列表是要包含的特定包的列表。再说一遍,有时候Py2Exe就是找不到东西。我以前必须在这里包括电子邮件、pycrypto或lxml。请注意,如果排除列表包含您试图包含在包或包含列表中的内容,那么Py2Exe可能会继续排除这些内容。

  • dll_excludes -排除项目中不需要的DLL。

选项 字典,我们还有其他一些选择要看。这个 压缩的 键告诉py2exe是否压缩zipfile(如果已设置)。这个 优化 键设置优化级别。零不是优化,2是最高的。通过设置 优化 到2,我们可以将文件夹的大小减少大约1兆字节。这个 bundle_files 密钥在zipfile或exe中捆绑DLL。bundle文件的有效值为:

  • 1=捆绑所有东西,包括python解释器。

  • 2=捆绑除python解释器之外的所有东西

  • 3=不捆绑(默认)

几年前,当我第一次学习Py2Exe时,我在他们的邮件列表上问我最好的选择是什么,因为我在捆绑包选项1上遇到了问题。我听说3号可能是最稳定的。我同意了,不再有随机问题,所以这是我目前的建议。如果不喜欢分发多个文件,请将其压缩或创建安装程序。我在此列表中使用的唯一其他选项是 dist_dir 一个。我使用它来尝试不同的构建选项,或者在我不想覆盖我的主要好的构建时创建自定义的构建。您可以在Py2Exe网站上阅读所有其他选项。

py2exe包不支持在其二进制文件中包含python eggs,因此如果您安装了应用程序作为egg依赖的包,那么在创建可执行文件时,它将无法工作。您必须确保您的依赖项安装正常。

总结

此时,您应该足够了解自己开始使用py2exe。你现在可以忙着分发你最新的作品了。应注意,Py2Exe有几种替代品,例如 B冻结cx_freezePyInstaller .你应该至少尝试其他两个来看看他们的比较。创建可执行文件可能会令人沮丧,但要有耐心并坚持不懈。Python打包社区非常愿意提供帮助。你只需要问问。