cx_Freeze 应用程序不会在命令提示符下打开并且不会打印任何错误
cx_Freeze app will not open in command prompt and prints no errors
首先,我在 Windows 10.
上使用 python 3.6.5 和 cx_Freeze 6.0b1
我有一个使用 wxPython 构建的程序,想使用 cx_Freeze 冻结代码。我已经为此工作了好几天,并且已经阅读了关于此问题的每个 post 的感受,但仍然没有取得任何成功。 运行 命令提示符或双击应用程序中的 .exe 将无法打开。我还尝试更改 None
、Console
和 Win32GUI
之间的 base
,但都没有成功。
此时我已经快要放弃了。我会很高兴只是得到一个错误信息追下去。
setup.py
:
import os
import sys
from cx_Freeze import setup, Executable
os.environ['TCL_LIBRARY'] = r'C:\Users\Chad\Anaconda3\Library\lib\tcl8.6'
os.environ['TK_LIBRARY'] = r'C:\Users\Chad\Anaconda3\Library\lib\tk8.6'
include_lst = []
package_lst = ['numpy', 'scipy', 'pulp', 'pubsub', 'sqlite3',
'numpy.core._methods']
exclude_lst = ['matplotlib', 'tkinter', 'PyQt4.QtSql', 'PyQt5',
'PyQt4.QtNetwork', 'PyQt4.QtScript', 'sqlalchemy']
base = None
setup (
name='',
version='',
author='',
author_email='',
options={'build_exe':
{'packages': package_lst,
'excludes': exclude_lst,
'include_files': include_lst,
'include_msvcr': True
}
},
executables=[Executable('main.py', base=base, icon=None)]
)
我可以毫无问题地冻结以下程序,所以这可能不是 cx_Freeze 问题,而是我的 main.py 文件中的问题?
if __name__.endswith('__main__'):
print('Hello World')
至于准备一个最小的例子,我很抱歉,但我不确定如何去做,因为这个程序确实使用了一个 sqlite3 数据库和大约 21 个内部模块。但是,在尝试时我认为问题出在连接到数据库上,所以下面是一个基本示例,但如果没有数据库,我怀疑您是否会因为数据库问题而重现。有了这段代码,一旦我冻结它,命令就不会发生任何事情,它只会转到下一行。
main.py
:
import util
import wx
class MasterPage (wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.conn = util.DataBaseManager.DataBaseManager()
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()
self.statusbar = self.CreateStatusBar(2)
self.statusbar.SetStatusWidths([self.W * 67, self.W * .23])
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()
util.DataBaseManager.py
:
import pandas as pd
import sys
import os
import sqlite3
class DataBaseManager(object):
def __init__(self):
"""Creates a connection to the database requested"""
try:
self.db = self.findDataPath('master.db')
self.conn = sqlite3.connect(self.db)
self.cursor = self.conn.cursor()
except sqlite3.Error as e:
print(e)
def executePandasQuery(self, sql_statement):
self.df = pd.read_sql_query(sql_statement, self.conn)
self.conn.commit()
return self.df
def executeCursorQuery(self, sql_statement, values):
if values == 'na':
self.cursor.execute(sql_statement)
else:
self.cursor.execute(sql_statement, values)
self.conn.commit()
return self.cursor
def __del__(self):
self.conn.close()
def findDataPath(self, filename):
"""
Get the correct path for outside data works with cx_freeze
:params str filename: the filename looking for
:returns: the absolute path of the file.
:rtype: string
"""
if getattr(sys, 'frozen', False):
# The application is frozen
p = os.path.abspath(os.path.dirname(sys.argv[0]))
p = '{}\{}'.format(p,filename)
else:
# The application is not frozen
p = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
p = '{}\{}'.format(p,filename)
return p
编辑#2
我认为这是导入我的自定义模块的问题 util
。如果我在 main.py
中的 import util
之前放置打印语句,打印语句将 运行 但随后应用程序关闭,命令提示符转到下一行。
关于连接数据库的问题:如何在冻结的应用程序中创建数据库文件master.db
,它位于何处?查看您发布的代码,我了解以下内容:
非冻结应用中,master.db
文件在util
包目录(主应用目录)的父目录下
您没有告诉 cx_Freeze
将 master.db
文件显式包含到构建目录中。由于这个文件在主应用程序目录中,它不会被 cx_Freeze
自动包含(查看构建目录以查看是否看到该文件)。
我看到至少有两种方法可以解决这个问题:
将master.db
文件移动到非冻结应用程序中的util
包目录中。 cx_Freeze
应该包括整个 util
目录,包括数据库文件。将 findDataPath
函数更改为:
def findDataPath(self, filename):
"""
Get the correct path for outside data works with cx_freeze
:params str filename: the filename looking for
:returns: the absolute path of the file.
:rtype: string
"""
p = os.path.dirname(os.path.abspath(__file__))
p = os.path.join(p, filename)
return p
这应该适用于非冻结和冻结的应用程序。 (备注:使用 os.path.join
以独立于平台的方式加入路径)。
将 master.db
文件保存在非冻结应用程序的主目录中,并告诉 cx_Freeze
将数据库文件包含到 lib
子目录中 build
目录,即冻结应用中util
包目录的父目录。您可以通过将元组 (source
、destination
) 传递到安装脚本中 include_files
列表选项的相应条目,让 cx_Freeze
将文件包含到特定位置:
include_lst = [('master.db', os.path.join('lib', 'master.db'))]
将您的 findDataPath
函数更改为:
def findDataPath(self, filename):
"""
Get the correct path for outside data works with cx_freeze
:params str filename: the filename looking for
:returns: the absolute path of the file.
:rtype: string
"""
p = os.path.dirname((os.path.dirname(os.path.abspath(__file__)))
p = os.path.join(p, filename)
return p
这也适用于非冻结和冻结应用程序。
首先,我在 Windows 10.
上使用 python 3.6.5 和 cx_Freeze 6.0b1我有一个使用 wxPython 构建的程序,想使用 cx_Freeze 冻结代码。我已经为此工作了好几天,并且已经阅读了关于此问题的每个 post 的感受,但仍然没有取得任何成功。 运行 命令提示符或双击应用程序中的 .exe 将无法打开。我还尝试更改 None
、Console
和 Win32GUI
之间的 base
,但都没有成功。
此时我已经快要放弃了。我会很高兴只是得到一个错误信息追下去。
setup.py
:
import os
import sys
from cx_Freeze import setup, Executable
os.environ['TCL_LIBRARY'] = r'C:\Users\Chad\Anaconda3\Library\lib\tcl8.6'
os.environ['TK_LIBRARY'] = r'C:\Users\Chad\Anaconda3\Library\lib\tk8.6'
include_lst = []
package_lst = ['numpy', 'scipy', 'pulp', 'pubsub', 'sqlite3',
'numpy.core._methods']
exclude_lst = ['matplotlib', 'tkinter', 'PyQt4.QtSql', 'PyQt5',
'PyQt4.QtNetwork', 'PyQt4.QtScript', 'sqlalchemy']
base = None
setup (
name='',
version='',
author='',
author_email='',
options={'build_exe':
{'packages': package_lst,
'excludes': exclude_lst,
'include_files': include_lst,
'include_msvcr': True
}
},
executables=[Executable('main.py', base=base, icon=None)]
)
我可以毫无问题地冻结以下程序,所以这可能不是 cx_Freeze 问题,而是我的 main.py 文件中的问题?
if __name__.endswith('__main__'):
print('Hello World')
至于准备一个最小的例子,我很抱歉,但我不确定如何去做,因为这个程序确实使用了一个 sqlite3 数据库和大约 21 个内部模块。但是,在尝试时我认为问题出在连接到数据库上,所以下面是一个基本示例,但如果没有数据库,我怀疑您是否会因为数据库问题而重现。有了这段代码,一旦我冻结它,命令就不会发生任何事情,它只会转到下一行。
main.py
:
import util
import wx
class MasterPage (wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.conn = util.DataBaseManager.DataBaseManager()
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()
self.statusbar = self.CreateStatusBar(2)
self.statusbar.SetStatusWidths([self.W * 67, self.W * .23])
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()
util.DataBaseManager.py
:
import pandas as pd
import sys
import os
import sqlite3
class DataBaseManager(object):
def __init__(self):
"""Creates a connection to the database requested"""
try:
self.db = self.findDataPath('master.db')
self.conn = sqlite3.connect(self.db)
self.cursor = self.conn.cursor()
except sqlite3.Error as e:
print(e)
def executePandasQuery(self, sql_statement):
self.df = pd.read_sql_query(sql_statement, self.conn)
self.conn.commit()
return self.df
def executeCursorQuery(self, sql_statement, values):
if values == 'na':
self.cursor.execute(sql_statement)
else:
self.cursor.execute(sql_statement, values)
self.conn.commit()
return self.cursor
def __del__(self):
self.conn.close()
def findDataPath(self, filename):
"""
Get the correct path for outside data works with cx_freeze
:params str filename: the filename looking for
:returns: the absolute path of the file.
:rtype: string
"""
if getattr(sys, 'frozen', False):
# The application is frozen
p = os.path.abspath(os.path.dirname(sys.argv[0]))
p = '{}\{}'.format(p,filename)
else:
# The application is not frozen
p = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
p = '{}\{}'.format(p,filename)
return p
编辑#2
我认为这是导入我的自定义模块的问题 util
。如果我在 main.py
中的 import util
之前放置打印语句,打印语句将 运行 但随后应用程序关闭,命令提示符转到下一行。
关于连接数据库的问题:如何在冻结的应用程序中创建数据库文件master.db
,它位于何处?查看您发布的代码,我了解以下内容:
非冻结应用中,
master.db
文件在util
包目录(主应用目录)的父目录下您没有告诉
cx_Freeze
将master.db
文件显式包含到构建目录中。由于这个文件在主应用程序目录中,它不会被cx_Freeze
自动包含(查看构建目录以查看是否看到该文件)。
我看到至少有两种方法可以解决这个问题:
将
master.db
文件移动到非冻结应用程序中的util
包目录中。cx_Freeze
应该包括整个util
目录,包括数据库文件。将findDataPath
函数更改为:def findDataPath(self, filename): """ Get the correct path for outside data works with cx_freeze :params str filename: the filename looking for :returns: the absolute path of the file. :rtype: string """ p = os.path.dirname(os.path.abspath(__file__)) p = os.path.join(p, filename) return p
这应该适用于非冻结和冻结的应用程序。 (备注:使用
os.path.join
以独立于平台的方式加入路径)。将
master.db
文件保存在非冻结应用程序的主目录中,并告诉cx_Freeze
将数据库文件包含到lib
子目录中build
目录,即冻结应用中util
包目录的父目录。您可以通过将元组 (source
、destination
) 传递到安装脚本中include_files
列表选项的相应条目,让cx_Freeze
将文件包含到特定位置:include_lst = [('master.db', os.path.join('lib', 'master.db'))]
将您的
findDataPath
函数更改为:def findDataPath(self, filename): """ Get the correct path for outside data works with cx_freeze :params str filename: the filename looking for :returns: the absolute path of the file. :rtype: string """ p = os.path.dirname((os.path.dirname(os.path.abspath(__file__))) p = os.path.join(p, filename) return p
这也适用于非冻结和冻结应用程序。