首先,我在Windows 10上使用python 3.6.5和cx_Freeze 6.0b1。
我有一个使用wxPython构建的程序,想使用cx_Freeze冻结代码。我已经为此工作了好几天,并且已经阅读了关于此问题的每篇文章,但仍然没有取得成功。在命令提示符下运行.exe或双击该应用程序将不会打开。我也曾尝试在base
,None
和Console
之间更改Win32GUI
,但均未成功。
这时我要放弃了。我很乐意得到一条错误消息来追逐。
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 db和内部模块中的21个。但是,在尝试时,我认为问题出在连接数据库,因此下面是一个基本示例,但是如果没有db,我怀疑由于db问题您将可以重现。有了这段代码,一旦冻结,就不会在命令上发生任何事情,它只会转到下一行。
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
时遇到的问题。如果我在import util
中的main.py
前面放了一条打印语句,则该打印语句将运行,但应用程序将关闭,命令提示符转到下一行。
答案 0 :(得分:0)
关于连接数据库的问题:如何在冻结的应用程序中创建数据库文件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
的{{1}}子目录中目录,它是冻结应用程序中build
软件包目录的父目录。您可以通过将元组(util
,cx_Freeze
)传递到设置脚本中source
列表选项的相应条目,来使destination
将文件包含到特定位置:
include_files
将您的include_lst = [('master.db', os.path.join('lib', 'master.db'))]
函数更改为:
findDataPath
这对于非冻结应用程序和冻结应用程序也都适用。