Python的项目中,如果想要在其他的电脑上运行你的代码,那么相对于C/C#等静态语言来说,可能并不是这么容易。因为动态语言运行需要解释器。这就意味着其他电脑上必须要有和你的开发环境相同的解释器和运行环境。那么有没有办法像C/C#那样一次编译到处使用呢?
答案是肯定的,以IronPython 2.7为例:官方提供了一个pyc.py的工具,可以在:IronPython 2.7\Tools\Scripts路径下找到。使用它可以将我们的代码打包为.exe可执行文件,无论是纯脚本还是带有UI交互窗口的项目,都能打包,使用方法如下:
可以在文件pyc.py的开头找到
pyc: The Command-Line Python Compiler
Usage: ipy.exe pyc.py [options] file [file ...]
Options:
/out:output_file Output file name (default is main_file.<extenstion>)
/target:dll Compile only into dll. Default
/target:exe Generate console executable stub for startup in addition to dll.
/target:winexe Generate windows executable stub for startup in addition to dll.
@<file> Specifies a response file to be parsed for input files and command line options (one per line)
/file_version:<version> Set the file/assembly version
/? /h This message
EXE/WinEXE specific options:
/main:main_file.py Main file of the project (module to be executed first)
/platform:x86 Compile for x86 only
/platform:x64 Compile for x64 only
/embed Embeds the generated DLL as a resource into the executable which is loaded at runtime
/standalone Embeds the IronPython assemblies into the stub executable.
/mta Set MTAThreadAttribute on Main instead of STAThreadAttribute, only valid for /target:winexe
/file_info_product:<name> Set product name in executable meta information
/file_info_product_version:<version> Set product version in executable meta information
/file_info_company:<name> Set company name in executable meta information
/file_info_copyright:<info> Set copyright information in executable meta information
/file_info_trademark:<info> Set trademark information in executable meta information
Example:
ipy.exe pyc.py /main:Program.py Form.py /target:winexe
"""
需要提醒的是:/target:的选择,如果你的程序是在命令行窗口跑的,那么选exe或者winexe都无所谓,区别只是错误提示的显示方式会有变化而已。但是,如果程序中是带有UI窗口的,例如Ironpython WPF项目,那么打包的时候就只能选择/tagrget:winexe,否则在Load窗口的时候会出现多线程失败。
好了,打包其实也就这么简单,下一个问题是在别的机器上面跑,因为Ironpython是基于.Net实现的Python解释器,那么同样的,运行Ironpython的及其也需要安装.Net,Ironpython2.7至少需要.Net 4.0。这是其一。
其二,如果您知识按照上面Example里面说的,指定/main:还有一些自己写的.py文件,那么一般情况下,在别的机器上都会跑不了,注意我说的是一般情况下,因为不用系统或者第三方提供的Library实在是很少。绝大多数情况下双击运行就会提醒你:import xxx fail, can not find xxx之类的错误,说白了就是找不到你要包含的库,这是为什么呢?不是已经打包好了吗?
实际上,这是个非常容易坑人的点,因为pyc在打包的时候并不会将整个运行环境都打包,而是仅仅将基本的解释器以及命令行参数输入的文件进行打包,其他的诸如os,cmd.base64这样的库统统都不会打包进我们的.exe执行文件中,这样就会导致写好的代码因为缺少常用的Library支撑而无法运行。
解决方法如下:将所有项目中依赖的Library以及项目文件统统加入到打包文件行列,例如下面的代码:
#!/usr/bin/env ipy
import sys
import os
import base64
if(__name__ == "__main__"):
print "Hello,World"
我包含了sys,os和base64这三个系统Library,那么在打包的时候,就需要如下的命令:
ipy.exe pyc.py /main:main.py os.py sys.py base64.py /target:exe
但是,这样打包产生的exe仍然无法运行,原因是os或者sys里面仍然会有import其他依赖Library的行为,所以不仅要将我们项目中依赖的Library加入到打包的行列,Library所依赖的Library也要加入到打包的行列中。
这样看是不是就觉得这样打包还不如不打包,因为整个依赖关系错综复杂,这样来得太麻烦了,光是查找依赖项就会消磨掉我们不少的时间,所以这里推荐直接将所有的Library文件全部加入到打包的文件序列中即可,虽然会导致产生的exe文件过大,动辄数十MB,但是相对于易用性和可移植性来看,空间的牺牲是值得的。可以说是当前的万全之策。
说一说目前pyc的缺点:
1、只能打包单一的.py拓展名文件
2、没有自动添加依赖Library的功能
优点:
1、官方打包工具,相对于CPython的打包工具使用较简单
2、支持命令行窗口和GUI窗口程序的打包