cx_Freeze 应用立即关闭且没有错误

cx_Freeze app closes right away with no errors

我的 cx_Freeze 应用程序在我打开时关闭并且没有打印错误。安装文件运行没有错误。我相信这与我的主要代码中的导入有关。我使用了 python 3.6.5 cx_Freeze 6.0b1 和 windows 10.

setup.py

import os
from cx_Freeze import setup, Executable

include_lst = []

package_lst = ['numpy', 'scipy', 'pulp', 'pubsub', 'sqlite3', 'pandas',
               'wx', 'functools', 'sklearn', 'numpy.core._methods']

exclude_lst = ['matplotlib', 'tkinter', 'PyQt4.QtSql', 'PyQt5',
               'PyQt4.QtNetwork', 'PyQt4.QtScript', 'sqlalchemy']

base = None

setup (
       name='test',
       version='0.01',
       author='test',
       author_email='Omitted',
       options={'build_exe':
                   {'packages': package_lst,
                    'excludes': exclude_lst,
                    'include_files': include_lst
                   }
                },
       executables=[Executable('main_.py',  base=base, icon=icon_file)]
       )

当我冻结这个基本示例时,它可以正常工作

main.py

import wx


class MasterPage (wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.createFrame()

    def createFrame(self):
        self.width, self.height = wx.GetDisplaySize()
        self.SetTitle('Test')
        self.SetSize(wx.Size((self.width-50, self.height-50)))
        self.SetMinSize((1080, 720))
        self.W, self.H = self.GetSize()
        self.Bind(wx.EVT_CLOSE, self.onQuit)
        self.Centre()

    def onQuit(self, event):
        """Checks to make sure the user wants to leave the program"""
        dlg = wx.MessageDialog(self,'Do you really want to quit?',
                           'Confirm Exit',
                            wx.ICON_QUESTION|wx.OK|wx.CANCEL )
        result = dlg.ShowModal()
        dlg.Destroy
        if result == wx.ID_OK:
            self.Destroy()

if __name__.endswith('__main__'):
    app = wx.App()
    MasterPage(None).Show()
    app.MainLoop()

但是当我在 import wx 行上方添加 import pandasimport <any module> 时,cx_Freeze 应用程序会在我打开后立即关闭

main.py

import pandas
import wx


class MasterPage (wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.createFrame()

    def createFrame(self):
        self.width, self.height = wx.GetDisplaySize()
        self.SetTitle('Test')
        self.SetSize(wx.Size((self.width-50, self.height-50)))
        self.SetMinSize((1080, 720))
        self.W, self.H = self.GetSize()
        self.Bind(wx.EVT_CLOSE, self.onQuit)
        self.Centre()

    def onQuit(self, event):
        """Checks to make sure the user wants to leave the program"""
        dlg = wx.MessageDialog(self,'Do you really want to quit?',
                           'Confirm Exit',
                            wx.ICON_QUESTION|wx.OK|wx.CANCEL )
        result = dlg.ShowModal()
        dlg.Destroy
        if result == wx.ID_OK:
            self.Destroy()

if __name__.endswith('__main__'):
    app = wx.App()
    MasterPage(None).Show()
    app.MainLoop()

我也试过将导入放在 try except 语句中,它仍然无法打开并且没有错误打印

main.py

try:
    import pandas
except Exception as e:
    print(e)
import wx


class MasterPage (wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.createFrame()

    def createFrame(self):
        self.width, self.height = wx.GetDisplaySize()
        self.SetTitle('Test')
        self.SetSize(wx.Size((self.width-50, self.height-50)))
        self.SetMinSize((1080, 720))
        self.W, self.H = self.GetSize()
        self.Bind(wx.EVT_CLOSE, self.onQuit)
        self.Centre()

    def onQuit(self, event):
        """Checks to make sure the user wants to leave the program"""
        dlg = wx.MessageDialog(self,'Do you really want to quit?',
                           'Confirm Exit',
                            wx.ICON_QUESTION|wx.OK|wx.CANCEL )
        result = dlg.ShowModal()
        dlg.Destroy
        if result == wx.ID_OK:
            self.Destroy()

if __name__.endswith('__main__'):
    app = wx.App()
    MasterPage(None).Show()
    app.MainLoop()

我什至在 import 语句之前和 import 语句之后添加了打印语句,第一个打印语句运行然后应用程序关闭。

main.py

print('app started')
import pandas
print('import worked')
import wx


class MasterPage (wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.createFrame()

    def createFrame(self):
        self.width, self.height = wx.GetDisplaySize()
        self.SetTitle('Test')
        self.SetSize(wx.Size((self.width-50, self.height-50)))
        self.SetMinSize((1080, 720))
        self.W, self.H = self.GetSize()
        self.Bind(wx.EVT_CLOSE, self.onQuit)
        self.Centre()

    def onQuit(self, event):
        """Checks to make sure the user wants to leave the program"""
        dlg = wx.MessageDialog(self,'Do you really want to quit?',
                           'Confirm Exit',
                            wx.ICON_QUESTION|wx.OK|wx.CANCEL )
        result = dlg.ShowModal()
        dlg.Destroy
        if result == wx.ID_OK:
            self.Destroy()

if __name__.endswith('__main__'):
    app = wx.App()
    MasterPage(None).Show()
    app.MainLoop()

有趣的是,pandastkinter(而不是 wx)之间类似的明显导入冲突已发布在

  1. 我不熟悉 wx。首先,我认为您应该使用 base = "Win32GUI" 作为 Windows 下的 GUI 应用程序(参见 cx_Freeze documentation)。在安装脚本中将 base = None 替换为以下行:

    # GUI applications require a different base on Windows (the default is for a console application).
    import sys
    base = None
    if sys.platform == "win32":
        base = "Win32GUI"
    
  2. 由于您已将 scipy 添加到 packages 选项列表,因此您还需要将 scipy.spatial.cKDTree 添加到 excludes 选项列表(请参阅this issue):

    exclude_lst = ['matplotlib', 'tkinter', 'PyQt4.QtSql', 'PyQt5',
                   'PyQt4.QtNetwork', 'PyQt4.QtScript', 'sqlalchemy',
                   'scipy.spatial.cKDTree']
    
  3. 您可能还需要将 sqlite3.dll 添加到 include_files 选项列表才能使用 sqlite3(我不确定):

    PYTHON_INSTALL_DIR = os.path.dirname(os.path.dirname(os.__file__))
    include_lst = [(os.path.join(PYTHON_INSTALL_DIR, 'DLLs', 'sqlite3.dll'), os.path.join('lib', 'sqlite3.dll'))]
    
  4. 最后,我建议您从 cmd 提示中启动您的应用程序,以确保收到所有错误消息:

    • 启动 cmd 提示(在开始菜单中键入 cmd
    • 切换到生成冻结可执行文件的构建目录
    • 启动冻结的可执行文件

如果您仍然收到任何进一步的错误消息,请将其添加到您的问题中。