python文件的编译

背景知识

  1. pyc文件: .pyc 是一种二进制文件,是由 .py 文件经过编译后,生成一种byte code文件。 .py 文件变成 .pyc 文件后,加载的速度有所提高,而且 .pyc 是一种跨平台的字节码,是由python的虚拟机来执行的,这个类似于JAVA或者.NET的虚拟机的概念。 .pyc 的内容是跟python的版本相关的,不同版本编译后的 .pyc 文件是不同的,2.5编译的 .pyc 文件对于2.4版本的python是无法执行的。
  2. pyo文件: .pyo 是优化编译后的程序  python -O 源文件 即可将源程序编译为 .pyo 文件。
  3. pyd文件: .pyd 是python的动态链接库。

 

为什么要编译Python文件?

通常Python代码是不需要编译就可以运行的,但Python其实也是有编译的过程的,与Java和C#一样Python只能执行字节码,Python只是将编译过程隐藏起来了。将Python文件编译为 .pyc 或 .pyo 文件有两个目的:

  1. 由于 .py 文件是可以直接看到源码的,所以如果是开发商业软件的话就需要将 .py 文件编译为看不到源代码的 .pyc 字节码文件后再发布出去;
  2. 将 .py 文件编译为 .pyc 或 .pyo 文件可以提高Python程序的加载速度,而且 .pyc 是一种跨平台的字节码,由python的虚拟机来执行;

python的编译过程

  当我们通过下面的命令来运行一个Python程序时:(Linux中)

1 Python test.py
2 
3 
4 # test.py中的内容
5 # --------------------------------------------------------
6 #!/usr/bin/env python
7 import mymodule
8 mymodule.say("hello")

Python解释器其实并不一定会读入 mymodule.py 文件,它会尝试读取 mymodule.pyc 文件或者 mymodule.pyo 文件。如果都失败了,或者 mymodule.py 文件比 mymodule.pyc/mymodule.pyo 新,才转而读入 mymodule.py 文件。Python只懂得解释执行字节码,所以 mymodule.py 文件读入后第一件事就是先进行编译。编译的结果会被尝试保存到 mymodule.pyc 文件中。Python的编译实际上主要是进行文法分析,生成一个抽象语法树,然后转储成字节码形式。这一点与Java有些相似,因为它们都生成字节码。

编译Python文件的方法(Linux)

  编译 .py 文件有以下几种方式,所有这些方式都是使用了 py_compile 模块的 compile() 方法。同时我们可以使用 compileall 模块中的 compile_dir() 来编译某个文件夹下面所有的 .py 文件,以及可以使用 compile_path 来依次编译 sys.path 指定路径下的 .py 文件。如果看过 compileall 模块的源码我们可以知道 compileall 编译 .py 文件其实还是调用了 py_compile 的 compile() 方法。

  在Linux环境下,可以通过写一个bash脚本编译 .py 文件,也可以直接通过命令行来编译。(这里仅介绍通过命令行来编译的方法):

1. 生成单个的 .pyc  or  .pyo 文件

 1 # 编译成pyc文件
 2 # ------------------------------------------------------
 3 python -m py_compile $filename    # 其中,$filename是要编译的python源码文件名
 4 
 5 
 6 # 编译成pyo文件
 7 # -------------------------------------------------------
 8 python -O -m py_compile $filename
 9 # 或者
10 python -OO -m py_compile $filename
11 
12 # 其中, + -O选项表示优化产生的字节码,优化程度由PYTHONOPTIMIZE(environment)的值来决定。 + -OO选项表示在-O优化的基础上移除所有的doc-strings(文档文本)。

2. 批量生成 .pyc 文件

  使用compileall模块可以批量编译整个目录下的Python源码文件。

1 # 函数定义
2 compileall.compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, quiet=False, legacy=False, optimize=-1)
3 
4 # 用法:
5 python -m compileall $dir

或者可以编写脚本来实现:

1 import compileall
2 compileall.compile_dir('$dir')
3 
4 # 其中,$dir 为Python源代码所在的目录。

 

posted @ 2016-04-06 09:54  会心一击  阅读(23644)  评论(0编辑  收藏  举报