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