cxfreeze打包python程序的方法说明(生成安装包,实现桌面快捷方式、删除快捷方式)

发布时间:2025-12-09 14:02:26 浏览次数:3

一、cxfreeze基础

1、cxfreeze功能

python代码文件转exe方法有三种,分别是cx_freeze,py2exe,PyInstaller,这三种方式各有千秋,本人只用过py2exe和cxfreeze,这里重点说明cxfreeze。

2、安装包下载地址

https://sourceforge.net/projects/cx-freeze/files/

3、cxfree的官方说明文档

http://cx-freeze.readthedocs.io/en/latest/distutils.html

二、cxfreeze使用方法

1、cxfreeze命令方法

cxfreeze etax.py –target-dir out/ #把etax.py 打包成etax.exe,放在out目录下

2、编写cxsetup.py编译脚本,然后用py去执行。

来一个简单的需求:编译etax.py生成test.exe文件。

a、步骤1,先编写一个cxsetup.py脚本文件

#coding=utf-8
#cxsetup.py代码
fromcx_Freezeimportsetup,Executable
setup(
name=”test”,
version=”1.0″,
description=”Test application”,
author=”zhongtang”,
executables=[Executable(“etax.py”)]
)

可以看到,cxsetup.py其实是一个py程序,该程序调用了cx_Freeze 包中的setup、Executable类。

然后用python执行cxsetup.py,就可以实现编译exe。

另外补充一点,cxsetup.py可以随意起名,默认都叫xxsetup.py

编译后的文件属性如下:

b、步骤2,执行py命令

#build方式打包成exe文件,可以脱离python环境运行

python cxsetup.py build

#bdist_msi方式可以打包成windows下msi格式的安装包文件

python cxsetup.py bdist_msi

三、cxsetup.py程序的进阶写法

还是以一个实例说明,需求如下:

1、et是一个基于wxpython编写的图形界面的小程序

2、et中使用了ini配置文件,文件名为et.ini

3、et中使用了PIL类,并使用图片文件et.jpg

4、et程序一共包含4个文件,主程序名为eTMain.py

5、打包py成exe,脱离python环境运行

6、生成windows下的msi安装包,该安装包运行后会安装桌面快捷方式、开始菜单快捷方式、删除程序的快捷方式,并且开始菜单有子目录。

上cxsetup.py代码

#!/usr/bin/python
#coding=utf-8
#createby:joshuazou2016.7.23

importsys
importtraceback
fromcx_Freezeimportsetup,Executable
importmsilib

#Dependenciesareautomaticallydetected,butitmightneedfinetuning.

#中文需要显式用gbk方式编码
product_name=u‘异体‘.encode(‘gbk‘)
unproduct_name=u‘卸载异体‘.encode(‘gbk‘)
product_desc=u“异体客户端程序Ver1.0“.encode(“gbk“)

#uuid叫通用唯一识别码,后面再卸载快捷方式中要用到
product_code=msilib.gen_uuid()
#主程序手动命名
target_name=‘etMain.exe‘

build_exe_options={
“include_files“:[“et.ini“,“et.jpg“,’data’],
#包含外围的ini、jpg文件,以及data目录下所有文件,以上所有的文件路径都是相对于cxsetup.py的路径。
“packages“:[“os“,“wx“],#包含用到的包
“includes“:[“PIL“,“traceback“],
“excludes“:[“tkinter“],#提出wx里tkinter包
“path“:sys.path,#指定上述的寻找路径
“icon“:“et.ico”#指定ico文件
};

#快捷方式表,这里定义了三个快捷方式
shortcut_table=[

#1、桌面快捷方式
(“DesktopShortcut“,#Shortcut
“DesktopFolder“,#Directory_,必须在Directory表中
product_name,#Name
“TARGETDIR“,#Component_,必须在Component表中
“[TARGETDIR]“+target_name,#Target
None,#Arguments
product_desc,#Description
None,#Hotkey
None,#Icon
None,#IconIndex
None,#ShowCmd
‘TARGETDIR‘#WkDir
),

#2、开始菜单快捷方式
(“StartupShortcut“,#Shortcut
“MenuDir“,#Directory_
product_name,#Name
“TARGETDIR“,#Component_
“[TARGETDIR]“+target_name,#Target
None,#Arguments
product_desc,#Description
None,#Hotkey
None,#Icon
None,#IconIndex
None,#ShowCmd
‘TARGETDIR‘#WkDir
),

#3、程序卸载快捷方式
(“UniShortcut“,#Shortcut
“MenuDir“,#Directory_
unproduct_name,#Name
“TARGETDIR“,#Component_
“[System64Folder]msiexec.exe“,#Target
r“/x“+product_code,#Arguments
product_desc,#Description None,#Hotkey None,#Icon None,#IconIndex None,#ShowCmd ‘TARGETDIR’#WkDir ) ] #手动建设的目录,在这里定义。 ”’ 自定义目录说明: ============== 1、3个字段分别为Directory,Directory_Parent,DefaultDir 2、字段1指目录名,可以随意命名,并在后面直接使用 3、字段2是指字段1的上级目录,上级目录本身也是需要预先定义,除了某些系统自动定义的目录,譬如桌面快捷方式中使用DesktopFolder 参考网址https://msdn.microsoft.com/en-us/library/aa372452(v=vs.85).aspx ”’ directories=[ (“ProgramMenuFolder”,”TARGETDIR”,”.”), (“MenuDir”,“ProgramMenuFolder”,product_name) ] #Nowcreatethetabledictionary #也可把directories放到data里。 ”’ 快捷方式说明: ============ 1、windows的msi安装包文件,本身都带一个installdatabase,包含很多表(用一个Orca软件可以看到)。 2、下面的Directory、Shortcut都是msi数据库中的表,所以冒号前面的名字是固定的(貌似大小写是区分的)。 3、data节点其实是扩展很多自定义的东西,譬如前面的directories的配置,其实cxfreeze中代码的内容之一,就是把相关配置数据写入到msi数据库的对应表中 参考网址:https://msdn.microsoft.com/en-us/library/aa367441(v=vs.85).aspx ”’ msi_data={#”Directory”:directories, “Shortcut”:shortcut_table } #ChangesomedefaultMSIoptionsandspecifytheuseoftheabovedefinedtables #注意product_code是我扩展的,现有的官网cx_freeze不支持该参数,为此简单修改了cx_freeze包的代码,后面贴上修改的代码。 bdist_msi_options={‘data’:msi_data, ‘upgrade_code’:‘{9f21e33d-48f7-cf34-33e9-efcfd80eed10}’, ‘add_to_path’:False, ‘directories’:directories, ‘product_code’:product_code, ‘initial_target_dir’:r'[ProgramFilesFolder]\%s’%(product_name)} #GUIapplicationsrequireadifferentbaseonWindows(thedefaultisfora #consoleapplication). base=None; ifsys.platform==“win32”: base=“Win32GUI” #简易方式定义快捷方式,放到Executeable()里。 #shortcutName=“AppName”, #shortcutDir=“ProgramMenuFolder” setup(name=“et”, author=’etchinacorp’, version=“1.0”, description=product_desc.decode(‘gbk’), options={“build_exe”:build_exe_options, “bdist_msi”:bdist_msi_options}, executables=[Executable(“etMain.py”, targetName=target_name, compress=True, base=base) ])

四、补充说明

1、有关windows install msi 文件

可以去microsoft的官网学习学习,https://msdn.microsoft.com/en-us/library/aa372860(v=vs.85).aspx

2、Orca编辑工具

查看修改msi文件数据库表的工具,Orca(msi编辑工具) 4.5.6 中文绿色版。

绝对堪称神器,贴个图片,这玩意太棒了(本文很多写法就是仿照python2.7的安装文件的数据,结合cxfree代码琢磨出来的)。

3、扩展的cxfreeze代码

前文在cxsetup.exe中我提到自定义了product_code参数,这个参数在官方版本的cxfreeze是不支持的(官方版本的productcode是直接写死的代码msilib.gen_uuid())。

所以扩展product_code配置的目的,就是因为在卸载Shortcut,需要用到 msiexec.exe /x {productcode}。

修改原理:

将 msilib.gen_uuid()放到cxsetup.py中,并作为product_code参数传给cxfreeze。

在cxfreeze中判断product_code参数是否定义,没定义则默认取msilib.gen_uuid(),有定义则使用定义值。

修改点:

cx_Free/windist.py文件。

修改点1、

class bdist_msi(distutils.command.bdist_msi.bdist_msi):
user_options = distutils.command.bdist_msi.bdist_msi.user_options + [
(‘add-to-path=’, None, ‘add target dir to PATH environment variable’),
(‘upgrade-code=’, None, ‘upgrade code to use’),
(‘initial-target-dir=’, None, ‘initial target directory’),
(‘target-name=’, None, ‘name of the file to create’),
(‘directories=’, None, ‘list of 3-tuples of directories to create’),
(‘data=’, None, ‘dictionary of data indexed by table name’),
# add by joshua zou 2016.07.23
(‘product-code=’, None, ‘product code to use’)
]

修改点2、

def finalize_options(self):
distutils.command.bdist_msi.bdist_msi.finalize_options(self)
name = self.distribution.get_name()
fullname = self.distribution.get_fullname()
if self.initial_target_dir is None:
if distutils.util.get_platform() == “win-amd64”:
programFilesFolder = “ProgramFiles64Folder”
else:
programFilesFolder = “ProgramFilesFolder”
self.initial_target_dir = r”[%s]\%s” % (programFilesFolder, name)
if self.add_to_path is None:
self.add_to_path = False
if self.target_name is None:
self.target_name = fullname
if not self.target_name.lower().endswith(“.msi”):
platform = distutils.util.get_platform().replace(“win-“, “”)
self.target_name = “%s-%s.msi” % (self.target_name, platform)
if not os.path.isabs(self.target_name):
self.target_name = os.path.join(self.dist_dir, self.target_name)
if self.directories is None:
self.directories = []
if self.data is None:
self.data = {}
# add by joshua zou 2016.7
if self.product_code is None:
self.product_code = msilib.gen_uuid()

修改点3、

def initialize_options(self):
distutils.command.bdist_msi.bdist_msi.initialize_options(self)
self.upgrade_code = None
self.add_to_path = None
self.initial_target_dir = None
self.target_name = None
self.directories = None
self.data = None
# add by joshua zou 2016.7
self.product_code=None

代码点4、

def run(self):
if not self.skip_build:
self.run_command(‘build’)
install = self.reinitialize_command(‘install’, reinit_subcommands = 1)
install.prefix = self.bdist_dir
install.skip_build = self.skip_build
install.warn_dir = 0
distutils.log.info(“installing to %s”, self.bdist_dir)
install.ensure_finalized()
install.run()
self.mkpath(self.dist_dir)
fullname = self.distribution.get_fullname()
if os.path.exists(self.target_name):
os.unlink(self.target_name)
metadata = self.distribution.metadata
author = metadata.author or metadata.maintainer or “UNKNOWN”
version = metadata.get_version()
sversion = “%d.%d.%d” % \
distutils.version.StrictVersion(version).version
”’
modified by joshua zou 2016.7
self.db = msilib.init_database(self.target_name, msilib.schema,
self.distribution.metadata.name, msilib.gen_uuid(), sversion,
author)
”’
self.db = msilib.init_database(self.target_name, msilib.schema,
self.distribution.metadata.name, self.product_code, sversion,
author)
msilib.add_tables(self.db, msilib.sequence)

完整源码

importdistutils.command.bdist_msi
importdistutils.errors
importdistutils.util
importmsilib
importos

__all__=[“bdist_msi”]

#forcetheremoveexistingproductsactiontohappenfirstsinceWindows
#installerappearstobebraindeadanddoesn’thandlefilessharedbetween
#different“products”verywell
sequence=msilib.sequence.InstallExecuteSequence

forindex,infoinenumerate(sequence):
ifinfo[0]==‘RemoveExistingProducts‘:
sequence[index]=(info[0],info[1],1450)

classbdist_msi(distutils.command.bdist_msi.bdist_msi):
user_options=distutils.command.bdist_msi.bdist_msi.user_options+[
(‘add-to-path=‘,None,‘addtargetdirtoPATHenvironmentvariable‘),
(‘upgrade-code=‘,None,‘upgradecodetouse‘),
(‘initial-target-dir=‘,None,‘initialtargetdirectory‘),
(‘target-name=‘,None,‘nameofthefiletocreate‘),
(‘directories=‘,None,‘listof3-tuplesofdirectoriestocreate‘),
(‘data=‘,None,‘dictionaryofdataindexedbytablename‘),
#addbyjoshuazou2016.07.23
(‘product-code=‘,None,‘productcodetouse‘)
]
x=y=50
width=370
height=300
title=“[ProductName]Setup“
modeless=1
modal=3

defadd_config(self,fullname):
ifself.add_to_path:
msilib.add_data(self.db,‘Environment‘,
[(“E_PATH“,“Path“,r“[~];[TARGETDIR]“,“TARGETDIR“)])
ifself.directories:
msilib.add_data(self.db,“Directory“,self.directories)
msilib.add_data(self.db,‘CustomAction‘,
[(“A_SET_TARGET_DIR“,256+51,“TARGETDIR“,
self.initial_target_dir)])
msilib.add_data(self.db,‘InstallExecuteSequence‘,
[(“A_SET_TARGET_DIR“,‘TARGETDIR=””‘,401)])
msilib.add_data(self.db,‘InstallUISequence‘,
[(“PrepareDlg“,None,140),
(“A_SET_TARGET_DIR“,‘TARGETDIR=””‘,401),
(“SelectDirectoryDlg“,“notInstalled“,1230),
(“MaintenanceTypeDlg“,
“InstalledandnotResumeandnotPreselected“,1250),
(“ProgressDlg“,None,1280)
])
forindex,executableinenumerate(self.distribution.executables):
ifexecutable.shortcutNameisnotNone\
andexecutable.shortcutDirisnotNone:
baseName=os.path.basename(executable.targetName)
msilib.add_data(self.db,“Shortcut“,
[(“S_APP_%s”%index,executable.shortcutDir,
executable.shortcutName,“TARGETDIR“,
“[TARGETDIR]%s”%baseName,None,None,None,
None,None,None,None)])
fortableName,datainself.data.items():
msilib.add_data(self.db,tableName,data)

defadd_cancel_dialog(self):
dialog=msilib.Dialog(self.db,“CancelDlg“,50,10,260,85,3,
self.title,“No“,“No“,“No“)
dialog.text(“Text“,48,15,194,30,3,
“Areyousureyouwanttocancel[ProductName]installation?“)
button=dialog.pushbutton(“Yes“,72,57,56,17,3,“Yes“,“No“)
button.event(“EndDialog“,“Exit“) button=dialog.pushbutton(“No”,132,57,56,17,3,“No”,“Yes”) button.event(“EndDialog”,“Return”) defadd_error_dialog(self): dialog=msilib.Dialog(self.db,“ErrorDlg”,50,10,330,101,65543, self.title,“ErrorText”,None,None) dialog.text(“ErrorText”,50,9,280,48,3,“”) fortext,xin[(“No”,120),(“Yes”,240),(“Abort”,0), (“Cancel”,42),(“Ignore”,81),(“Ok”,159),(“Retry”,198)]: button=dialog.pushbutton(text[0],x,72,81,21,3,text,None) button.event(“EndDialog”,“Error%s”%text) defadd_exit_dialog(self): dialog=distutils.command.bdist_msi.PyDialog(self.db,“ExitDialog”, self.x,self.y,self.width,self.height,self.modal, self.title,“Finish”,“Finish”,“Finish”) dialog.title(“Completingthe[ProductName]installer”) dialog.back(“<Back”,“Finish”,active=False) dialog.cancel(“Cancel”,“Back”,active=False) dialog.text(“Description”,15,235,320,20,0x30003, “ClicktheFinishbuttontoexittheinstaller.”) button=dialog.next(“Finish”,“Cancel”,name=“Finish”) button.event(“EndDialog”,“Return”) defadd_fatal_error_dialog(self): dialog=distutils.command.bdist_msi.PyDialog(self.db,“FatalError”, self.x,self.y,self.width,self.height,self.modal, self.title,“Finish”,“Finish”,“Finish”) dialog.title(“[ProductName]installerendedprematurely”) dialog.back(“<Back”,“Finish”,active=False) dialog.cancel(“Cancel”,“Back”,active=False) dialog.text(“Description1”,15,70,320,80,0x30003, “[ProductName]setupendedprematurelybecauseofanerror.” “Yoursystemhasnotbeenmodified.Toinstallthisprogram” “atalatertime,pleaseruntheinstallationagain.”) dialog.text(“Description2”,15,155,320,20,0x30003, “ClicktheFinishbuttontoexittheinstaller.”) button=dialog.next(“Finish”,“Cancel”,name=“Finish”) button.event(“EndDialog”,“Exit”) defadd_files(self): db=self.db cab=msilib.CAB(“distfiles”) f=msilib.Feature(db,“default”,“DefaultFeature”,“Everything”,1, directory=”TARGETDIR”) f.set_current() rootdir=os.path.abspath(self.bdist_dir) root=msilib.Directory(db,cab,None,rootdir,“TARGETDIR”, “SourceDir”) db.Commit() todo=[root] whiletodo: dir=todo.pop() forfileinos.listdir(dir.absolute): ifos.path.isdir(os.path.join(dir.absolute,file)): newDir=msilib.Directory(db,cab,dir,file,file, “%s|%s”%(dir.make_short(file),file)) todo.append(newDir) else: dir.add_file(file) cab.commit(db) defadd_files_in_use_dialog(self): dialog=distutils.command.bdist_msi.PyDialog(self.db,“FilesInUse”, self.x,self.y,self.width,self.height,19,self.title, “Retry”,“Retry”,“Retry”,bitmap=False) dialog.text(“Title”,15,6,200,15,0x30003, r”{\DlgFontBold8}FilesinUse”) dialog.text(“Description”,20,23,280,20,0x30003, “Somefilesthatneedtobeupdatedarecurrentlyinuse.”) dialog.text(“Text”,20,55,330,50,3, “Thefollowingapplicationsareusingfilesthatneedtobe” “updatedbythissetup.Closetheseapplicationsandthen” “clickRetrytocontinuetheinstallationorCanceltoexit” “it.”) dialog.control(“List”,“ListBox”,20,107,330,130,7, “FileInUseProcess”,None,None,None) button=dialog.back(“Exit”,“Ignore”,name=“Exit”) button.event(“EndDialog”,“Exit”) button=dialog.next(“Ignore”,“Retry”,name=“Ignore”) button.event(“EndDialog”,“Ignore”) button=dialog.cancel(“Retry”,“Exit”,name=“Retry”) button.event(“EndDialog”,“Retry”) defadd_maintenance_type_dialog(self): dialog=distutils.command.bdist_msi.PyDialog(self.db, “MaintenanceTypeDlg”,self.x,self.y,self.width,self.height, self.modal,self.title,“Next”,“Next”,“Cancel”) dialog.title(“Welcometothe[ProductName]SetupWizard”) dialog.text(“BodyText”,15,63,330,42,3, “Selectwhetheryouwanttorepairorremove[ProductName].”) group=dialog.radiogroup(“RepairRadioGroup”,15,108,330,60,3, “MaintenanceForm_Action”,“”,“Next”) group.add(“Repair”,0,18,300,17,“&Repair[ProductName]”) group.add(“Remove”,0,36,300,17,“Re&move[ProductName]”) dialog.back(“<Back”,None,active=False) button=dialog.next(“Finish”,“Cancel”) button.event(“[REINSTALL]”,“ALL”, ‘MaintenanceForm_Action=”Repair”‘,5) button.event(“[Progress1]”,“Repairing”, ‘MaintenanceForm_Action=”Repair”‘,6) button.event(“[Progress2]”,“repairs”, ‘MaintenanceForm_Action=”Repair”‘,7) button.event(“Reinstall”,“ALL”, ‘MaintenanceForm_Action=”Repair”‘,8) button.event(“[REMOVE]”,“ALL”, ‘MaintenanceForm_Action=”Remove”‘,11) button.event(“[Progress1]”,“Removing”, ‘MaintenanceForm_Action=”Remove”‘,12) button.event(“[Progress2]”,“removes”, ‘MaintenanceForm_Action=”Remove”‘,13) button.event(“Remove”,“ALL”, ‘MaintenanceForm_Action=”Remove”‘,14) button.event(“EndDialog”,“Return”, ‘MaintenanceForm_Action<>”Change”‘,20) button=dialog.cancel(“Cancel”,“RepairRadioGroup”) button.event(“SpawnDialog”,“CancelDlg”) defadd_prepare_dialog(self): dialog=distutils.command.bdist_msi.PyDialog(self.db,“PrepareDlg”, self.x,self.y,self.width,self.height,self.modeless, self.title,“Cancel”,“Cancel”,“Cancel”) dialog.text(“Description”,15,70,320,40,0x30003, “Pleasewaitwhiletheinstallerpreparestoguideyouthrough” “theinstallation.”) dialog.title(“Welcometothe[ProductName]installer”) text=dialog.text(“ActionText”,15,110,320,20,0x30003, “Pondering…”) text.mapping(“ActionText”,“Text”) text=dialog.text(“ActionData”,15,135,320,30,0x30003,None) text.mapping(“ActionData”,“Text”) dialog.back(“Back”,None,active=False) dialog.next(“Next”,None,active=False) button=dialog.cancel(“Cancel”,None) button.event(“SpawnDialog”,“CancelDlg”) defadd_progress_dialog(self): dialog=distutils.command.bdist_msi.PyDialog(self.db,“ProgressDlg”, self.x,self.y,self.width,self.height,self.modeless, self.title,“Cancel”,“Cancel”,“Cancel”,bitmap=False) dialog.text(“Title”,20,15,200,15,0x30003, r”{\DlgFontBold8}[Progress1][ProductName]”) dialog.text(“Text”,35,65,300,30,3, “Pleasewaitwhiletheinstaller[Progress2][ProductName].”) dialog.text(“StatusLabel”,35,100,35,20,3,“Status:”) text=dialog.text(“ActionText”,70,100,self.width–70,20,3, “Pondering…”) text.mapping(“ActionText”,“Text”) control=dialog.control(“ProgressBar”,“ProgressBar”,35,120,300, 10,65537,None,“Progressdone”,None,None) control.mapping(“SetProgress”,“Progress”) dialog.back(“<Back”,“Next”,active=False) dialog.next(“Next>”,“Cancel”,active=False) button=dialog.cancel(“Cancel”,“Back”) button.event(“SpawnDialog”,“CancelDlg”) defadd_properties(self): metadata=self.distribution.metadata props=[ (‘DistVersion’,metadata.get_version()), (‘DefaultUIFont’,‘DlgFont8’), (‘ErrorDialog’,‘ErrorDlg’), (‘Progress1’,‘Install’), (‘Progress2’,‘installs’), (‘MaintenanceForm_Action’,‘Repair’), (‘ALLUSERS’,‘1’) ] email=metadata.author_emailormetadata.maintainer_email ifemail: props.append((“ARPCONTACT”,email)) ifmetadata.url: props.append((“ARPURLINFOABOUT”,metadata.url)) ifself.upgrade_codeisnotNone: props.append((“UpgradeCode”,self.upgrade_code)) msilib.add_data(self.db,‘Property’,props) defadd_select_directory_dialog(self): dialog=distutils.command.bdist_msi.PyDialog(self.db, “SelectDirectoryDlg”,self.x,self.y,self.width,self.height, self.modal,self.title,“Next”,“Next”,“Cancel”) dialog.title(“Selectdestinationdirectory”) dialog.back(“<Back”,None,active=False) button=dialog.next(“Next>”,“Cancel”) button.event(“SetTargetPath”,“TARGETDIR”,ordering=1) button.event(“SpawnWaitDialog”,“WaitForCostingDlg”,ordering=2) button.event(“EndDialog”,“Return”,ordering=3) button=dialog.cancel(“Cancel”,“DirectoryCombo”) button.event(“SpawnDialog”,“CancelDlg”) dialog.control(“DirectoryCombo”,“DirectoryCombo”,15,70,272,80, 393219,“TARGETDIR”,None,“DirectoryList”,None) dialog.control(“DirectoryList”,“DirectoryList”,15,90,308,136,3, “TARGETDIR”,None,“PathEdit”,None) dialog.control(“PathEdit”,“PathEdit”,15,230,306,16,3, “TARGETDIR”,None,“Next”,None) button=dialog.pushbutton(“Up”,306,70,18,18,3,“Up”,None) button.event(“DirectoryListUp”,“0”) button=dialog.pushbutton(“NewDir”,324,70,30,18,3,“New”,None) button.event(“DirectoryListNew”,“0”) defadd_text_styles(self): msilib.add_data(self.db,‘TextStyle’, [(“DlgFont8”,“Tahoma”,9,None,0), (“DlgFontBold8”,“Tahoma”,8,None,1), (“VerdanaBold10”,“Verdana”,10,None,1), (“VerdanaRed9”,“Verdana”,9,255,0) ]) defadd_ui(self): self.add_text_styles() self.add_error_dialog() self.add_fatal_error_dialog() self.add_cancel_dialog() self.add_exit_dialog() self.add_user_exit_dialog() self.add_files_in_use_dialog() self.add_wait_for_costing_dialog() self.add_prepare_dialog() self.add_select_directory_dialog() self.add_progress_dialog() self.add_maintenance_type_dialog() defadd_upgrade_config(self,sversion): ifself.upgrade_codeisnotNone: msilib.add_data(self.db,‘Upgrade’, [(self.upgrade_code,None,sversion,None,513,None, “REMOVEOLDVERSION”), (self.upgrade_code,sversion,None,None,257,None, “REMOVENEWVERSION”) ]) defadd_user_exit_dialog(self): dialog=distutils.command.bdist_msi.PyDialog(self.db,“UserExit”, self.x,self.y,self.width,self.height,self.modal, self.title,“Finish”,“Finish”,“Finish”) dialog.title(“[ProductName]installerwasinterrupted”) dialog.back(“<Back”,“Finish”,active=False) dialog.cancel(“Cancel”,“Back”,active=False) dialog.text(“Description1”,15,70,320,80,0x30003, “[ProductName]setupwasinterrupted.Yoursystemhasnot” “beenmodified.Toinstallthisprogramatalatertime,” “pleaseruntheinstallationagain.”) dialog.text(“Description2”,15,155,320,20,0x30003, “ClicktheFinishbuttontoexittheinstaller.”) button=dialog.next(“Finish”,“Cancel”,name=“Finish”) button.event(“EndDialog”,“Exit”) defadd_wait_for_costing_dialog(self): dialog=msilib.Dialog(self.db,“WaitForCostingDlg”,50,10,260,85, self.modal,self.title,“Return”,“Return”,“Return”) dialog.text(“Text”,48,15,194,30,3, “Pleasewaitwhiletheinstallerfinishesdeterminingyour” “diskspacerequirements.”) button=dialog.pushbutton(“Return”,102,57,56,17,3,“Return”, None) button.event(“EndDialog”,“Exit”) deffinalize_options(self): distutils.command.bdist_msi.bdist_msi.finalize_options(self) name=self.distribution.get_name() fullname=self.distribution.get_fullname() ifself.initial_target_dirisNone: ifdistutils.util.get_platform()==“win-amd64”: programFilesFolder=“ProgramFiles64Folder” else: programFilesFolder=“ProgramFilesFolder” self.initial_target_dir=r”[%s]\%s”%(programFilesFolder,name) ifself.add_to_pathisNone: self.add_to_path=False ifself.target_nameisNone: self.target_name=fullname ifnotself.target_name.lower().endswith(“.msi”): platform=distutils.util.get_platform().replace(“win-“,“”) self.target_name=“%s-%s.msi”%(self.target_name,platform) ifnotos.path.isabs(self.target_name): self.target_name=os.path.join(self.dist_dir,self.target_name) ifself.directoriesisNone: self.directories=[] ifself.dataisNone: self.data={} #addbyjoshuazou2016.7 ifself.product_codeisNone: self.product_code=msilib.gen_uuid() definitialize_options(self): distutils.command.bdist_msi.bdist_msi.initialize_options(self) self.upgrade_code=None self.add_to_path=None self.initial_target_dir=None self.target_name=None self.directories=None self.data=None #addbyjoshuazou2016.7 self.product_code=None defrun(self): ifnotself.skip_build: self.run_command(‘build’) install=self.reinitialize_command(‘install’,reinit_subcommands=1) install.prefix=self.bdist_dir install.skip_build=self.skip_build install.warn_dir=0 distutils.log.info(“installingto%s”,self.bdist_dir) install.ensure_finalized() install.run() self.mkpath(self.dist_dir) fullname=self.distribution.get_fullname() ifos.path.exists(self.target_name): os.unlink(self.target_name) metadata=self.distribution.metadata author=metadata.authorormetadata.maintaineror“UNKNOWN” version=metadata.get_version() sversion=“%d.%d.%d”%\ distutils.version.StrictVersion(version).version ”’ modifiedbyjoshuazou2016.7 self.db=msilib.init_database(self.target_name,msilib.schema, self.distribution.metadata.name,msilib.gen_uuid(),sversion, author) ”’ self.db=msilib.init_database(self.target_name,msilib.schema, self.distribution.metadata.name,self.product_code,sversion, author) msilib.add_tables(self.db,msilib.sequence) self.add_properties() self.add_config(fullname) self.add_upgrade_config(sversion) self.add_ui() self.add_files() self.db.Commit() ifnotself.keep_temp: distutils.dir_util.remove_tree(self.bdist_dir, dry_run=self.dry_run)

五、总结

至此,cxfreeze的用法基本全了,更深入的用法,建议大家去阅读cxfreeze的源码。

学习python,个人觉得有几点非常关键:

一、查看官方帮助文档,二、阅读源码,三、借助google(百度上资料太少,而且相对不准确)

需要做网站?需要网络推广?欢迎咨询客户经理 13272073477