把Python脚本和所用到的库打包为exe文件,可以更方便的发布程序,避免使用程序的每个电脑都必须安装Python。 网上有不少相关介绍,但很少见到Python 3.x下打包Python脚本为exe的成功案例,笔者探索了一下,成功完成了任务,记录下来分享给需要的朋友。欢迎交流。一、Python 3.1的打包办法1、下载cx_Freeze。 http://sourceforge.net/projects/cx-freeze/files/ 根据自己的系统类型和Python版本下载合适的类型,我下载的是:cx_Freeze-4.1.2.win32-py3.1.msi。 这个工具目前最新版本是2010.1.6号的,还挺新的。2、安装。 直接安装下载的安装包。之后可以看到cxfreeze工具所在目录如下:
3、打包。我要打包的是BlogPost.py和它依赖的模块。 A、准备工作。 a、去除代码中所有中文字符,包括注释。(指定编码的注释可以不去掉没有关系) b、 如果用到类似lxml这样的第三方库,可能会出现找不到_elementpath模块的错误。需要在某个.py文件中写上import _elementpath as DONTUSE,并且指定该模块的搜索路径。(我的该模块所在路径是:C:\Python25\Lib\site-packages\lxml \_elementpath.py)B、命令行执行。C:\Python31\Scripts\cxfreeze.bat --include-path=C:\Python25\Lib\site-packages\lxml --init-script=D:\Projects\Google\pyblogpost\2exe\BlogPost.py BlogPost.py 注意:(1)--init-script指定的启动文件路径必须用绝对路径,否则会提示找不到init script。(2)只能指定一个要打包的模块,也就是启动模块。(3)所有.py文件都不能有中文字符,否则会出现编码异常。(4)执行上述命令后,在会生成dist目录,里面就有打包后的可执行文件。 (5)发布后,可执行文件执行路径不能有中文(最好也不要有空格)。而且最好发布dist目录所有文件,我发现有时只发布打包后的exe是无法运行的。 (6)启动执行的文件中不要有下面这种判断,否则可执行文件执行会没有任何效果。 if __name__ == "__main__": main()(7)如果没有指定--include-path,或者没有在某个.py文件中写上import _elementpath as DONTUSE,都会出现如下找不到_elementpath模块的错误: D:\Projects\Google\pyblogpost\2exe\dist>BlogPost.exe Traceback (most recent call last): File "D:\Projects\Google\pyblogpost\2exe\BlogPost.py", line 11, in import BlogConfig File "BlogConfig.py", line 5, in File "ExtensionLoader_lxml_etree.py", line 12, in File "lxml.etree.pyx", line 39, in init lxml.etree (src/lxml/lxml.etree.c:1399 44) ImportError: No module named _elementpath (8)不能有中文,即使是注释中也不能有,否则出现如下错误。 codeString = fp.read() File "C:\Python31\lib\codecs.py", line 300, in decode (result, consumed) = self._buffer_decode(data, self.errors, final) UnicodeDecodeError: 'utf8' codec can't decode bytes in position 557-558: invalid data 尝试把编码由cp936改为utf-8,也不可以,把文件中ASCII另存为UTF-8,也不行,有如下错误: File "BlogConfig.py", line 1 \ufeff#!/usr/bin/python ^ SyntaxError: invalid character in identifier 4、补充说明另外一种打包方式。 第3点讲的是通过命令行指定参数打包,也可以采用如下方式: (1)新建setup.py文件,内容大致如下:(我使用的是上述第3点讲述的方法,没有修改参数) (2)在命令行执行:python setup.py build 这种打包方法,在cxfreeze工具的sample中也大量使用。二、Python 2.x版本上面的cx_Freeze同样提供for Python 2.x的版本,用法我估计也差不多,不再赘述。加上这一节,是记录一下之前我用Python 2.x写一个小工具用py2exe打包的过程。先安装py2exe工具。然后用下面setup.py脚本: from distutils.core import setup import py2exe options = {"py2exe": {"bundle_files": 1}} setup(options = options, zipfile = None, console=["hello.py"],) 命令行执行: C:\Python26\python.exe setup.py py2exe 就会在dist目录生成单一的hello.exe文件,这个文件是可执行的。
我使用cxfreeze打包生成了一个python的exe程序,在我自己的win7环境下exe程序可以成功运行,在同事的没有python环境的win7环境下也可以成功运行。 但是到了生产环境下运行的时候出现了如下错误: 映像文件有效,但不适用于此计算机类型。 生产环境为windows server2003
cxfreeze script¶
The cxfreeze script is included with other Python scripts. On Windows and the Mac this is in theScripts subdirectory of your Python installation whereas on Unix platforms this in the bin directory of the prefix where Python is installed.
Assuming you have a script called hello.py which you want to turn into an executable, this can be accomplished by this command:
cxfreeze hello.py --target-dir dist
Further customization can be done using the following options:
option name | description |
---|---|
–version | show version number and exit |
-h, –help | show this help message and exit |
-O | optimize generated bytecode as per PYTHONOPTIMIZE; use -OO in order to remove doc strings |
-c, –compress | compress byte code in zip files |
-s, –silent | suppress all output except warnings |
–base-name | file on which to base the executable; if the name of the file is not an absolute file name, the subdirectory bases inside the cx_Freeze package will be searched for a file matching the name, without regard to the extension |
–init-script | script which will be executed upon startup; if the name of the file is not an absolute file name, the subdirectory initscripts inside the cx_Freeze package will be searched for a file matching the name, without regard to the extension |
–target-dir | directory in which to place the executable and any dependent files |
–target-name | the name of the file to create; the default is the base name of the script and the extension of the base executable name |
–shared-name | the name of the file to create; the default is the base name of the script and the extension of the base executable name |
–no-copy-deps | do not copy any dependent files (extensions, shared libraries, etc.) to the target directory; this also modifies the default init script to ConsoleKeepPath and means that the target executable requires a Python installation to execute properly |
–default-path | list of paths separated by the standard path separator for the platform which will be used to initialize the search path instead of sys.path |
–include-path | list of paths separated by the standard path separator for the platform which will be used to add to the search path |
–replace-paths | replace all the paths in modules found in the given paths with the given replacement string; multiple values are separated by the standard path separator for the platform and each value is of the form <search>=<replace>; <search> can be * which means all paths not already specified |
–include-modules | comma separated list of names of modules to include |
–exclude-modules | comma separated list of names of modules to exclude |
–ext-list-file | name of file in which to place the list of dependent files which were copied to the target directory |
-z, –zip-include | name of file to add to the zip file or a specification of the form <name>=<arcname> which will specify the archive name to use; multiple –zip-include arguments can be used |