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

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(
,
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,#DescriptionNone,#HotkeyNone,#IconNone,#IconIndexNone,#ShowCmd'TARGETDIR'#WkDir)]
1、3个字段分别为Directory,Directory_Parent,DefaultDir2、字段1指目录名,可以随意命名,并在后面直接使用3、字段2是指字段1的上级目录,上级目录本身也是需要预先定义,除了某些系统自动定义的目录,譬如桌面快捷方式中使用DesktopFolder参考网址https://msdn.microsoft.com/en-us/library/aa372452(v=vs.85).aspxdirectories=[("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).aspxmsi_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(,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",)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",)button.event("EndDialog","Exit")defadd_files(self):db=self.dbcab=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",)button.event("EndDialog","Exit")button=dialog.next("Ignore","Retry",)button.event("EndDialog","Ignore")button=dialog.cancel("Retry","Exit",)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.metadataprops=[('DistVersion',metadata.get_version()),('DefaultUIFont','DlgFont8'),('ErrorDialog','ErrorDlg'),('Progress1','Install'),('Progress2','installs'),('MaintenanceForm_Action','Repair'),('ALLUSERS','1')]email=metadata.author_emailormetadata.maintainer_emailifemail: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",)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=Falseifself.target_nameisNone:self.target_name=fullnameifnotself.target_name.lower().endswith(".msi"):platform=distutils.util.get_platform().replace("win-","")self.target_%(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.7ifself.product_codeisNone:self.product_code=msilib.gen_uuid()definitialize_options(self):distutils.command.bdist_msi.bdist_msi.initialize_options(self)self.upgrade_code=Noneself.add_to_path=Noneself.initial_target_dir=Noneself.target_name=Noneself.directories=Noneself.data=None#addbyjoshuazou2016.7self.product_code=Nonedefrun(self):ifnotself.skip_build:self.run_command('build')install=self.reinitialize_command('install',reinit_subcommands=1)install.prefix=self.bdist_dirinstall.skip_build=self.skip_buildinstall.warn_dir=0distutils.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.metadataauthor=metadata.authorormetadata.maintaineror"UNKNOWN"version=metadata.get_version()sversion="%d.%d.%d"%distutils.version.StrictVersion(version).version'''modifiedbyjoshuazou2016.7self.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(百度上资料太少,而且相对不准确)

以上。