天天看點

手動制作python的exe可執行程式 -- by Leo Jay

記錄下來以防以後找不到了。

python沒有内建一個編譯為exe的功能。給python程式的部署帶來不少的麻煩。

是以就會出現一些py2exe之類的很不錯的工具,用于自動把.py檔案編譯為.exe檔案。

最近抽空研究了一下手動實作類似py2exe的功能,希望加強對python的了解。

結果還相當不錯。把結果記錄下來,與大家共享。

文中所描述的方法,基于python的以下幾個功能

1. python程式運作時,會在sys.path指定的路徑中查找庫檔案。

2. python從2.3開始,支援從zip檔案中import庫(支援.py,.pyc和.pyo,但不支援.pyd)

3. python提供c api,讓c語言的程式,可以很友善的調用python的程式

注:假設python安裝在c:\python25目錄中,最後的可執行檔案放到d:\dist目錄中

1. 先去c:\python25\lib目錄,把所有檔案都複制出來,比如複制到d:\pythonlib目錄中

2. 開一個cmd視窗,進入d:\pythonlib目錄中,運作 python -oo compileall.py -f . 把lib中的.py檔案都編譯成.pyo檔案

3. 删除d:\pythonlib目錄中所有的.py和.pyc檔案,因為我們隻要有.pyo檔案就可以讓這些庫運作了。

4. 删除目錄中所有用不着的檔案,比如curses,test,idlelib,msilib等,以減少生成檔案的體積。

5. 把這些庫打包成一個zip檔案,比如stdlib.zip,放到d:\dist目錄中

6. 把c:\python25\dlls目錄中的.pyd和.dll檔案,複制到d:\dist\dlls目錄中,當然,删除不可能用到的一些檔案_msi.pyd,_ssl.pyd等等,可以減少檔案的體積

7. 把自己寫的程式,也按步驟2至步驟5所說的方法,打成一個mysrc.zip包,放到d:\dist目錄中。 注意:自己寫的程式的入口應該是main.pyo檔案

8. 用以下c程式編譯出一個可執行檔案,比方說叫runpy.exe,也放到d:\dist中。

 1

手動制作python的exe可執行程式 -- by Leo Jay

#include <python.h>

 2

手動制作python的exe可執行程式 -- by Leo Jay

#include <windows.h>

 3

手動制作python的exe可執行程式 -- by Leo Jay

#include <stdlib.h>

 4

手動制作python的exe可執行程式 -- by Leo Jay

#include <stdio.h>

 5

手動制作python的exe可執行程式 -- by Leo Jay

 6

手動制作python的exe可執行程式 -- by Leo Jay

int main()

 7

手動制作python的exe可執行程式 -- by Leo Jay

{

 8

手動制作python的exe可執行程式 -- by Leo Jay

        // 得到目前可執行檔案所在的目錄

 9

手動制作python的exe可執行程式 -- by Leo Jay

        char szpath[10240];

10

手動制作python的exe可執行程式 -- by Leo Jay

        char szcmd[10240];

11

手動制作python的exe可執行程式 -- by Leo Jay

        getmodulefilename(null, szpath, sizeof(szpath));

12

手動制作python的exe可執行程式 -- by Leo Jay

        char* p = strrchr(szpath, '\\');

13

手動制作python的exe可執行程式 -- by Leo Jay

        if (p == null)

14

手動制作python的exe可執行程式 -- by Leo Jay

        {

15

手動制作python的exe可執行程式 -- by Leo Jay

                printf("get module file name error!\n");

16

手動制作python的exe可執行程式 -- by Leo Jay

                return -1;

17

手動制作python的exe可執行程式 -- by Leo Jay

        }

18

手動制作python的exe可執行程式 -- by Leo Jay

19

手動制作python的exe可執行程式 -- by Leo Jay

        *p = 0;

20

手動制作python的exe可執行程式 -- by Leo Jay

21

手動制作python的exe可執行程式 -- by Leo Jay

        // 設定運作時的path

22

手動制作python的exe可執行程式 -- by Leo Jay

        sprintf(szcmd, "path=%s\\dlls;%%path%%", szpath);

23

手動制作python的exe可執行程式 -- by Leo Jay

        _putenv(szcmd);

24

手動制作python的exe可執行程式 -- by Leo Jay

25

手動制作python的exe可執行程式 -- by Leo Jay

        // 把sys.path設定為['.', '自己的源代碼zip檔案', '标準庫zip檔案', 'dll目錄']

26

手動制作python的exe可執行程式 -- by Leo Jay

        // 然後調用main子產品

27

手動制作python的exe可執行程式 -- by Leo Jay

        sprintf(szcmd,

28

手動制作python的exe可執行程式 -- by Leo Jay

                "import sys\n"

29

手動制作python的exe可執行程式 -- by Leo Jay

                "sys.path=['.', r'%s\\mysrc.zip', r'%s\\stdlib.zip', r'%s\\dlls']\n"

30

手動制作python的exe可執行程式 -- by Leo Jay

                "import main\n",

31

手動制作python的exe可執行程式 -- by Leo Jay

                szpath, szpath, szpath);

32

手動制作python的exe可執行程式 -- by Leo Jay

33

手動制作python的exe可執行程式 -- by Leo Jay

        py_optimizeflag = 2;

34

手動制作python的exe可執行程式 -- by Leo Jay

        py_nositeflag = 1;

35

手動制作python的exe可執行程式 -- by Leo Jay

        py_initialize();

36

手動制作python的exe可執行程式 -- by Leo Jay

        pyrun_simplestring(szcmd);

37

手動制作python的exe可執行程式 -- by Leo Jay

        return 0;

38

手動制作python的exe可執行程式 -- by Leo Jay

}

39

手動制作python的exe可執行程式 -- by Leo Jay

9. 把python25.dll放到d:\dist目錄中。

這樣來,d:\dist目錄中,一共隻有4個檔案加一個目錄:

dlls目錄:用于存放所有的dll檔案和pyd檔案

stdlib.zip檔案:用于存放所有的python的.pyo檔案格式的标準庫

mysrc.zip檔案:用于存放自己寫的程式。注意,自己寫的程式的入口在main.pyo中。

runpy.exe檔案:程式的啟動檔案,啟動後會設定python的sys.path,然後調用main子產品

python25.dll檔案:python的核心dll,runpy.exe依賴于這個dll

哈哈,相當的簡潔明了吧。一共才4個檔案一個目錄,5mb都不到哦。

注:當然,這種打包方式第一次做的時候比較麻煩,但之後就可以隻要把自己的程式打包就好了,其它的不用變。

而且,如果自己的程式經常做改動的話,自己的程式也可以不打包,直接放到d:\dist中,反正runpy.exe啟動程式的時候,隻要能正常運作import main就可以了。

解開包後,隻要用自己的程式替換mysrc.zip就可以使用了。

包裡有runpy.exe和runpyw.exe兩個檔案。其中,runpy.exe是控制台程式,runpyw.exe是非控制台程式。這兩個程式分别類似于python.exe和pythonw.exe。想讓程式運作時出現一個控制台,就運作runpy.exe,如果不想出現黑黑的控制台,就運作runpyw.exe。