Search code examples
python-3.xcx-freeze

cx_Freeze app closes right away with no errors


My cx_Freeze app closes when I open it and no errors print. The setup file runs with no errors. I believe it has something to do with imports in my main code. I used python 3.6.5 cx_Freeze 6.0b1 and 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)]
       )

When I freeze this basic example it works without any issues

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()

But when I add the import pandas or import <any module> above the import wx line the cx_Freeze app closes as soon as I open it

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()

I have also tried to put the import in a try except statement it still will not open and no errors print

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()

I even included a print statement before the import statement and after the import statement the first print statement runs then the app closes.

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()

Solution

  • Interestingly, a similar apparent import conflict between pandas and tkinter (instead of wx) has been posted in Error when building executable from Python3.6 script importing pandas using cx_Freeze.

    1. I'm not familiar with wx. First of all, I think you should use base = "Win32GUI" for a GUI application under Windows (see the cx_Freeze documentation). Replace base = None by the following lines in your setup script:

      # 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. As you have added scipy to the packages option list, you also need to add scipy.spatial.cKDTree to the excludes option list (see this issue):

      exclude_lst = ['matplotlib', 'tkinter', 'PyQt4.QtSql', 'PyQt5',
                     'PyQt4.QtNetwork', 'PyQt4.QtScript', 'sqlalchemy',
                     'scipy.spatial.cKDTree']
      
    3. You might also need to add sqlite3.dll to the include_files option list to be able to use sqlite3 (I'm not sure):

      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. Finally I would recommend to start your application from within a cmd prompt to be sure to get all error messages:

      • Start a cmd prompt (type cmd in the start menu)
      • Change to the build directory where your frozen executable has been generated
      • Start the frozen executable

    If you still get any further error message, please add it to your question.