重點:
- Python解釋過程: source code --> byte code --> JVM
- JIT 加速原理: 執行的時候將 一部分byte code 編譯成 機器代碼,替換原來的代碼
- 其他的Python實現: Cpython, JPython, IronPython, PyPy, Stackless…
- Frozen Binaries
Chap1: A Python Q&A Session
1.1 Downside
運行速度
簡而言之,標準的python實現,是將源代碼 編譯成中間語言,叫做
byte code
, 然後再解釋執行
爲了提高python的運行速度的問題,可以將邏輯部分使用python
編寫,而在需要性能的部分使用 C/C++編寫,然後再粘合,比如 著名的 numpy
1.2 Python能做什麼
- 系統編程
- GUI:
- tkinter
- PMW( 基於tkinter)
- wxPython(基於C++庫)
- Dabo(基於tkinter,wxPython等)
- Qt的工具
- Internet Scripting
- Component Integration
- Database Programming
- pickle, PyMongo, SQLObject, SQLAlchemy
- Rapid Prototyping
- Numeric and Scientific Programming
。。。
1.3 How Is Python Developed and Supported?
Python開發者在網上通過源代碼控制系統協調工作,每一次的變化都以一種正式協議的方式,其中包括寫 PEP(Python Enhancement Proposal) 或者其他文件。
1.4 Python的長處
- 面向對象,面向過程,函數式編程
- 函數式編程特色: generators, comprehensions, closures, maps, decorators, anonymous function lambdas, and first-class function objects
- 免費
- 可移植
- 強大
- 和其他語言混合
- 易學易用
Chap2: How Python Runs Programs
2.1 Python 解釋器
Python不僅是一門語言,也是一個編譯器的名稱。編譯器是一個軟件,用來執行其他的程序。當你寫了一個Python程序時,python解釋器能夠閱讀你的程序,並且執行這些命令。
當安裝Python解釋器的時候,它最少也包括了一個解釋器程序和一些支持性library。
2.2 程序執行
2.2.1 從程序員角度
python程序只是文本文件。 python文件以.py
結尾,但是從技術上來說,只有當文件被import
的時候,才必須要求文件以.py
結尾 。程序由解釋器一行一行執行。
2.2.2 從Python的角度
當讓Python去運行腳本的時候,python要先執行一些步驟,才能夠真正的運行你的代碼。具體來說,先將代碼編譯成一些叫做byte code
的東西,然後將它交給virtual machine
a. Byte code compilation
Python內部在執行程序的時候,先將源代碼編譯成一種byte code
的格式,byte code
是一種底層的,和平臺無關的源代碼表示。一條python語句,會被轉換成多條的byte code
指令。 這種轉換是爲了提升執行速度——Byte code
的運行比文本文件運行速度快很多。
如果python進程擁有機器上寫的權限,那麼它會把byte code
安裝在 .pyc
結尾的中。
在Python3.2
版本以前,運行了幾次程序後,我們將能在源文件的同一個目錄下,看到這些編譯後的文件; 而在3.2開始之後的版本,Python把會把這些.pyc byte code
放置在源文件目錄下的__pycache__
文件夾下,並且根據創建它們的python版本來命名他們,比如:script.cpython-33.pyc
檢查是否需要重新編譯:
無論在何種model
(將在Chap21中細講),下一次執行程序的時候,python會加載這些.pyc
並且跳過編譯過程,只要源文件沒有在上一次編譯後進行過更改,並且沒有使用和上一次編譯 不同的python版本運行過代碼。 具體步驟如下:
- 源代碼改變: Python會自動檢查源文件的上一次修改時間,去和
byte code
內容作比較,來判斷是否需要重新編譯 - Python版本變更:python也會根據
byte code
中的python版本信息,來決定這次是否需要重新編譯
Python如果沒有寫權限
程序仍然會正確運行,但是這些byte code
會在產生之後,被讀入內存中,然後在程序結束之後就被刪除。
因爲.pyc
文件能加速啓動時間,所以在大項目中,最好確保python有寫權限。
Byte code
能夠獨立於源代碼, 如果沒有源文件,只有.pyc
文件,那麼程序也能執行。
byte code只在被引入時產生
只有被import
的文件,纔會將對應的byte code
保存到文件中,最頂級的腳本程序入口文件不會被保存到文件,只會在內存中使用。
b.The Python Virtual Machine (PVM)
當程序被編譯之後,byte code
就會交付給 Python Virtual Machine來運行。
graph LR
A[源文件] --編譯--> B[Byte code]
B --交給--> C[Python虛擬機]
PVM本身並不是一個別的程序,它不需要單獨安裝。PVM本身就是一個大的代碼循環,遍歷你的代碼,一條條執行代碼的操作,它是 Python運行的引擎。它是在Python系統中,真正執行腳本的組件。技術上來說,它是所謂Python Interpreter的最後一步。
c. Performance implications
Python代碼不像完全編譯的語言一樣,直接編譯成機器碼,所以它的運行速度自然比機器代碼要慢;但它因爲有一步編譯,所以它的執行速度又比純解釋性語言快。
The net effect is that pure Python code runs at speeds somewhere between those of a traditional compiled language and a traditional interpreted language
d. Development implications
python並不區分 開發環境 和 部署環境,記住Python只有Runtime。
exec
,eval
等 built-ins, 能夠讀取字符串,將其當作python代碼運行
2.3 Execution Model Variations
上面講的python執行模式反映的是一種標準的python實現,但並不是一定的。隨着時間變化,會有其他的模式出現。
2.3.1 Python實現 的Alternatives
最基本的5種Python語言實現: CPython, Jython, IronPython, Stackless, and PyPy
- CPython: 最標準的實現。
- Jython(JPython): Python的另一種實現,爲的是讓python和Java結合在一起。 JPython包括一些Java類, 它們能將Python代碼編譯成 Java字節碼,然後給JVM運行。 不如CPython速度快和穩定
- IronPython: 和JPython差不多,是給 .NET用的
- Stackless–Python for concurrency: 重新實現的加強版CPython,爲的是Concurrency, 更適合
coroutine
,並且自己提供了microthreads
,比python自己的 線程和進程更好。 - PyPy–Python for speed: a drop-in replacement for CPython, 爲的是讓一部分程序運行更快, 提供了
Just-in-Time(JIT)
編譯器以及更快快速的 Python實現,提供了 sandbox tool來運行不安全代碼, 並且提供了之前Stackless
的系統。Just-in-Time(JIT)
編譯器以及更快快速的 Python實現,提供了 sandbox tool來運行不安全代碼, 並且提供了之前Stackless
的系統。
JIT 是 JVM的一個擴展,它把部分的
byte code
直接轉換成機器代碼,爲了提高速度。 它是在程序運行的時候做的轉換操作,並沒有一個 預編譯過程,並且JIT也能夠 通過跟蹤程序中每個對象的數據類型, 把動態類型的Python創建爲 明確類型的機器代碼。
2.3.2 Execution Optimization Tools
CPython及其之前提到的其他Python實現,在實現的時候都差不多: 將源代碼編譯成 byte code
, 然後再交給合適的 virtual machine執行。
其他系統,比如Cython hybrid, the Shed Skin C++ translator, and the just-in-time compilers in PyPy and Psyco
,試着進一步的優化這種 基本運行模式。
- Cython (A Python/C hybrid): is a hybrid language that combines Python code with the ability to call C functions and use C type declarations for variables, parameters, and class attributes. 嘗試將python代碼編譯成C代碼。
- Shed Skin (A Python-to-C++ translator): 試着將Python代碼轉換成C++代碼,再由電腦上的C++編譯器來編譯執行。
- Psyco (The original just-in-time compiler): 運行的時候將
byte code
進一步轉換成machine code,並且記錄了對象的數據類型。運行的時候,Psyco通過記錄各種傳遞對象的類型信息,來產生最優化、最有效率的 機器代碼。機器代碼產生後,它們就會替換掉原來的那部分byte code
來加快執行速度。 這個JIT和Java
的JIT不同,它是一種Specializing JIT Compiler, 它根據程序具體使用到的類型,在不同的情況下產生不同的機器代碼。
2.3.3 Frozen Binaries
有工具可以把Python程序直接打包成 可執行文件:
- py2exe
- PyInstaller
- py2app
- freeze
- cx_freeze
Frozen binaries 打包就是把Python編譯出來的 byte code
,PVM
,還有其他Python支持文件打包在一起。所以這個可執行文件中已經有了 Python環境,不需要機器本身自帶環境了。
2.3.4 Future Possibility
- 也許會有直接把Python代碼編譯成 機器代碼
- 也許會有新的
byte code
格式