把python脚本打包成二进制可执行程序的工具

Posted on 2015-05-12 18:42:29 by osdba

1. 工具的使用方法

此打包工具把python源代码打包成一个可执行的二进制文件。

$./pkgpy.py
Usage: ./pkgpy.py <pyfile> <exefile>

2. 示例

先建测试的脚本test01.py,内容如下:

#cat test01.py
#!/usr/bin/env python
# -*- coding:UTF-8

'''
Created on 2015-04-14

@author: tangcheng
'''

import sys
import os
import traceback

def main():
    print "Hello world"

if __name__ == "__main__":
    main()

测试过程如下:

$./pkgpy.py test01.py test01
Run: gcc -I/usr/include/python2.6 -lpython2.6 test01.c -o test01

$./test01
Hello world

实际上此打包程序把test01.py生成了如下C语言代码test01.c:

#include <Python.h>
#include <marshal.h>
static int g_file_size = 415;
static char g_codebuf[] = {0xd1,0xf2,0x0d,0x0a,0xff,0xcd,0x51,0x55,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x05,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x73,0x4f,0x00,0x00,0x00,0x64,0x00,
0x00,0x5a,0x00,0x00,0x64,0x01,0x00,0x64,0x02,0x00,0x6b,0x01,0x00,0x5a,0x01,0x00,
0x64,0x01,0x00,0x64,0x02,0x00,0x6b,0x02,0x00,0x5a,0x02,0x00,0x64,0x01,0x00,0x64,
0x02,0x00,0x6b,0x03,0x00,0x5a,0x03,0x00,0x64,0x03,0x00,0x84,0x00,0x00,0x5a,0x04,
0x00,0x65,0x05,0x00,0x64,0x04,0x00,0x6a,0x02,0x00,0x6f,0x0b,0x00,0x01,0x65,0x04,
0x00,0x83,0x00,0x00,0x01,0x6e,0x01,0x00,0x01,0x64,0x02,0x00,0x53,0x28,0x05,0x00,
0x00,0x00,0x73,0x2b,0x00,0x00,0x00,0x0a,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,
0x6f,0x6e,0x20,0x32,0x30,0x31,0x35,0x2d,0x30,0x34,0x2d,0x31,0x34,0x0a,0x0a,0x40,
0x61,0x75,0x74,0x68,0x6f,0x72,0x3a,0x20,0x74,0x61,0x6e,0x67,0x63,0x68,0x65,0x6e,
0x67,0x0a,0x69,0xff,0xff,0xff,0xff,0x4e,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x00,0x00,0x00,0x43,0x00,0x00,0x00,0x73,0x09,0x00,0x00,0x00,0x64,0x01,
0x00,0x47,0x48,0x64,0x00,0x00,0x53,0x28,0x02,0x00,0x00,0x00,0x4e,0x73,0x0b,0x00,
0x00,0x00,0x48,0x65,0x6c,0x6c,0x6f,0x20,0x77,0x6f,0x72,0x6c,0x64,0x28,0x00,0x00,
0x00,0x00,0x28,0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x00,
0x00,0x73,0x09,0x00,0x00,0x00,0x74,0x65,0x73,0x74,0x30,0x31,0x2e,0x70,0x79,0x74,
0x04,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x0e,0x00,0x00,0x00,0x73,0x02,0x00,0x00,
0x00,0x00,0x01,0x74,0x08,0x00,0x00,0x00,0x5f,0x5f,0x6d,0x61,0x69,0x6e,0x5f,0x5f,
0x28,0x06,0x00,0x00,0x00,0x74,0x07,0x00,0x00,0x00,0x5f,0x5f,0x64,0x6f,0x63,0x5f,
0x5f,0x74,0x03,0x00,0x00,0x00,0x73,0x79,0x73,0x74,0x02,0x00,0x00,0x00,0x6f,0x73,
0x74,0x09,0x00,0x00,0x00,0x74,0x72,0x61,0x63,0x65,0x62,0x61,0x63,0x6b,0x52,0x00,
0x00,0x00,0x00,0x74,0x08,0x00,0x00,0x00,0x5f,0x5f,0x6e,0x61,0x6d,0x65,0x5f,0x5f,
0x28,0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x00,0x73,
0x09,0x00,0x00,0x00,0x74,0x65,0x73,0x74,0x30,0x31,0x2e,0x70,0x79,0x74,0x08,0x00,
0x00,0x00,0x3c,0x6d,0x6f,0x64,0x75,0x6c,0x65,0x3e,0x08,0x00,0x00,0x00,0x73,0x0c,
0x00,0x00,0x00,0x06,0x02,0x0c,0x01,0x0c,0x01,0x0c,0x02,0x09,0x03,0x0d,0x01};

int main(int argc, char *argv[])
{
    int file_size;
    PyCodeObject *pycode;
    PyObject *mainmodule, *maindict;

    Py_Initialize();
    PySys_SetArgv(argc, argv);    
    mainmodule = PyImport_AddModule("__main__");
    maindict = PyModule_GetDict(mainmodule);
    pycode = (PyCodeObject *)PyMarshal_ReadObjectFromString(g_codebuf+8, g_file_size-8);
    PyEval_EvalCode(pycode, maindict, maindict);
    PyErr_Clear();
    Py_Finalize();
    return 0;
}

其中test01.c源码中全局变量g_codebuf是test01.pyc的内容。

3. 工具的下载地址

pkgpy.py