python2exe工作原理
python2exe使用python的modualfinder來調入要運行的scripts并且尋找運行它所需要的所有python模塊和擴展模塊。純python的模塊在臨時目錄里被編譯成.pyc(debug)和.pyo(optimized)的文件。編譯后的擴展模塊pyd文件也能找到。
最后生成一個與zip兼容的包,包含一個dependency目錄和你的script,這個包最后提供給一個py2exe自帶的python解釋器。運行生成的程序,將建立一個重要的關聯,這樣在script開始運行的時候,必要的模塊可以從zip包中正確地import.
由于擴展模塊不能從zip包中包含或import,它們以被單讀提供。放在dist\myscript目錄下。相似的工作:Gordon McMillan's installer(更成熟一些)
python2exe代碼分析
解碼的過程
main, winmain調用start函數。
start:
1)獲得目錄名和文件名(GetModuleFileName)
2)取出執行文件的數據(MapExistingFile)
3)獲得script的信息(GetScriptInfo)
4)用_putenv設置用戶的環境變量(PYTHONHOME,PYTHONPATH,PYTHONOPTIMIZE,PYTHONDEBUG等)
5)將scriptinfo種的信息來設置python內部變量(Py_NoSiteFlag, Py_VerboseFlag等)
6)Py_Initialize()
7)PySys_SetArgv(argc, argv)
8)調用BuildToc獲得toc(dict對象)
9)調用PyRun_SimpleString執行"import sys; sys.path=[r'%s']"
10)調用Load_Module調入imputil模塊,調用PyRun_SimpleString執行"import imputil"
11)Py_InitModule("__main__", methods);
12)解出Scripts\\support.py并運行它
13)解出Scripts\\__main__.py并運行它(這里的__main__.py就是要打包的python文件,被重命名為__main__.py)source\start.c:
1. MapExistingFile:用文件映像的方法打開文件,讀處理里面的內容
2. GetScriptInfo: 從archive.h中定義的(central directory record)格式的數據中取出script info(optimize, verbose, tag)到全局變量p_script_info中。具體地說明在http://ww.pkware.com/appnote.html
3. BuildToc:構造一個新的dict對象,在arch文件中做一個循環,取出所有的name放入dict中(PyDict_SetItem),其中調用了fixpath來解決"\"和"/"的統一問題,并將dict返回(注意,name好像是不帶后綴的)
4. extract_data: 使用zlib.h中定義的zstream結構,從archive結構中獲得指定的長度的數據
5. GetContentsFromOffset:計算位置,調用extract獲得數據
6. GetContents:利用PyDict_GetItemString從toc中得到指定的名字的文件的位置,調用GetContentsFromOffset獲得數據
7. Load_Module:檢查p_script_info->optimize,判斷文件名的后綴是".pyo"還是".pyc",調用GetContents從數據中調出這個文件。
8. get_code:指定名字,獲得這個文件的內容:GetContents + PyString_FromStringAndSize
試驗
用winzip可以打開生成的exe文件,說明這個exe實際是一個zip文件。
--
Though hope is frail
It's hard to kill
原文轉自:http://www.anti-gravitydesign.com