Python 介绍四 ——Py2exe

 
一、安装
Windows下直接下载安装包即可。
二、概述
Py2exe是将python程序转成可执行文件,这样,拷到其它机子下不用安装python及其它模块,也可以应用,网上很多人将这一过程称为软件打包。
这与我理解的软件打包还是有出入的,软件打包应该是将程序转成一个setup.exe,然后,可让用户,尽管过程差不多,但还是有点区别的,软件打包目前最著名的是install shield,可惜是商业软件,找了一个Inno Setup,免费的,还是有点费劲,如果只涉及一个exe就容易了,但包含动态链接库的就不是那么容易,反正,我还没用这东西把python打包成功过。
三、功能
1、基本功能
打包一般的程序很简单,是我看过python包最容易的一个,可能因为它功能太少的原因。
建立二个文件,一个叫Py2EXE.py,另一个叫setup.bat。其中Py2EXE.py的内容为:
from distutils.core import setup
import py2exe
setup(console=[ "test.py" ])
 
setup.bat是一个批处理文件,内容为:
python Py2EXE.py py2exe
这样我们就有三个文件,test.py、setup.bat、Py2EXE.py,将这三个文件放在同一目录双击setup.bat即可。运行后,得到两个文件夹build、dist,其中build是没有用的,可删除,dist文件夹中包含很多dll等文件,是运行程序所必须的,不可删除,要启动程序,可双击dist文件夹中有一个test.exe的可执行文件。
当然,名字是我取的,你爱怎么取就怎么取,只要对应就行。
2、涉及matplotlib库的软件打包
当然py2exe也不是那么容易,这也从一个侧面反映其不成熟,我试完test.py就很高兴,开始要打包工程,结果还是很不幸,后来才知道这是经典的错误, "RuntimeError: Could not find the matplotlib data files" 原因,py2exe打包时涉及到matplotlib库要做另外的处理,搞了一个下午,终于把它整出来,同样建立二个文件,只需要改Py2EXE的代码就行,代码贴出来看看:
 
#====================
Kill_Distro = True
MatPlotLib_Wanted = True
 
def File_Exists( path ):
        res=os.path.isdir(path)
        if res== True :
                return res
        return os.path.isfile(path)
 
from distutils.core import setup
import py2exe
import sys
 
import os
 
import shutil
import glob
 
homedir= r "E:/test/Matplotlib/multicolor"
 
python = r "c:/Python25" # Name of python directory
if File_Exists(python)== False :
        python = r "c:/Python23" # Name of python directory
 
#********************************************************************
# Some suggests that old build/dist should be cleared
#********************************************************************
dist_paths = [ homedir+ '//build' ,
                homedir+ '//dist' ]
for path in dist_paths :
        if File_Exists ( path ) :
                shutil.rmtree ( path )
 
#*******************************************************************
data_files = []
packages = []
includes = []
excludes = []
dll_excludes = []
data_files.append ( ( '' , glob.glob ( 'templates_*.*'
) ) )
 
# ******************************************************************
# For MatPlotLib
#*******************************************************************
if MatPlotLib_Wanted :
        import matplotlib
 
        includes.append ( 'matplotlib.numerix.random_array' )
 
        packages.append ( 'matplotlib' )
        packages.append ( 'pytz' )
 
        def mpl_data_files(destpath, path):
                mpl_data=[]
                for x in glob.glob (path+ '//*.*' ):
                        if os.path.isdir(x):
                                mpl_data_files(destpath+ '//' +os.path.split(x)[ 1 ],
x)
                        elif os.path.isfile(x):
                                mpl_data.append(x)
                data_files.append ( ( destpath, mpl_data))
 
        mpl_data_files(r 'matplotlibdata' ,
python+r '/Lib/site-packages/matplotlib/mpl-data' )
       
        data_files.append ( ( r 'matplotlibdata' , glob.glob (
       
python+r '/Lib/site-packages/matplotlib/mpl-data/matplotlibrc'
)))
        data_files.append ( ( r 'matplotlibdata/images' ,
glob.glob (
       
python+r '/Lib/site-packages/matplotlib/mpl-data/images/*.*'
)))
        data_files.append ( ( r 'matplotlibdata/fonts/afm' ,
glob.glob (
       
python+r '/Lib/site-packages/matplotlib/mpl-data/fonts/afm/*.*'
)))
        data_files.append ( (
r 'matplotlibdata/fonts/pdfcorefonts' , glob.glob (
       
python+r '/Lib/site-packages/matplotlib/mpl-data/fonts/pdfcorefonts/*.*' )))
        data_files.append ( ( r 'matplotlibdata/fonts/ttf' ,
glob.glob (
       
python+r '/Lib/site-packages/matplotlib/mpl-data/fonts/ttf/*.*'
)))
 
        excludes.append ( '_gtkagg' )
        excludes.append ( '_tkagg' )
        excludes.append ( '_agg2'  )
        excludes.append ( '_cairo' )
        excludes.append ( '_cocoaagg' )
        excludes.append ( '_fltkagg' )
        excludes.append ( '_gtk' )
        excludes.append ( '_gtkcairo' )
        excludes.append ( 'backend_qt' )
        excludes.append ( 'backend_qt4' )
        excludes.append ( 'backend_qt4agg' )
        excludes.append ( 'backend_qtagg' )
        excludes.append ( 'backend_cairo' )
        excludes.append ( 'backend_cocoaagg' )
        excludes.append ( 'tcl' )
        dll_excludes.append ( 'libgdk-win32-2.0-0.dll' )
        dll_excludes.append ( 'libgdk_pixbuf-2.0-0.dll' )
        dll_excludes.append ( 'libgobject-2.0-0.dll' )
        dll_excludes.append ( 'tcl84.dll' )
        dll_excludes.append ( 'tk84.dll' )
        dll_excludes.append ( 'tclpip84.dll' )
#*******************************************************************
# seems not to be found (imported in brick.py)
#includes.append ( 'PyLab_Works_properties' )
#********************************************************************
# If run without args, build executables, in quiet mode.
if len(sys.argv) == 1 :
        sys.argv.append( "py2exe" )
 
setup (
                windows = [ 'app.py' ] ,
                options = {
                        'py2exe' : {
                        'includes'      : includes,
                        'excludes'      : excludes,
                        'dll_excludes' : dll_excludes,
                        'packages'      : packages,
                        }
                },
                data_files = data_files
        )
 
result= 0
 
dist_paths = [ homeDir+ '//build' ,]
 
if (result== 0 ) and Kill_Distro :
        for path in dist_paths :
                if File_Exists ( path ) :
                        shutil.rmtree ( path )
 
这是完整的代码,还是有点麻烦。不过,总之能用就是最好的了。
之后,运行,你还会发现错误,不过这些错误就小菜一碟了,只要把程序中用到的数据拷到 dist 文件夹就行,这个你就不用担心,从错误提示中是很容易看出来的。

你可能感兴趣的:(python)