讀書筆記:LearningPython第五版 (第一、★二章: Python執行程序的過程)

重點:

  1. Python解釋過程: source code --> byte code --> JVM
  2. JIT 加速原理: 執行的時候將 一部分byte code 編譯成 機器代碼,替換原來的代碼
  3. 其他的Python實現: Cpython, JPython, IronPython, PyPy, Stackless…
  4. 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版本運行過代碼。 具體步驟如下:

  1. 源代碼改變: Python會自動檢查源文件的上一次修改時間,去和byte code內容作比較,來判斷是否需要重新編譯
  2. 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

  1. CPython: 最標準的實現。
  2. Jython(JPython): Python的另一種實現,爲的是讓python和Java結合在一起。 JPython包括一些Java類, 它們能將Python代碼編譯成 Java字節碼,然後給JVM運行。 不如CPython速度快和穩定
  3. IronPython: 和JPython差不多,是給 .NET用的
  4. Stackless–Python for concurrency: 重新實現的加強版CPython,爲的是Concurrency, 更適合 coroutine,並且自己提供了microthreads,比python自己的 線程和進程更好。
  5. 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,試着進一步的優化這種 基本運行模式。

  1. 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代碼。
  2. Shed Skin (A Python-to-C++ translator): 試着將Python代碼轉換成C++代碼,再由電腦上的C++編譯器來編譯執行。
  3. 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程序直接打包成 可執行文件:

  1. py2exe
  2. PyInstaller
  3. py2app
  4. freeze
  5. cx_freeze

Frozen binaries 打包就是把Python編譯出來的 byte codePVM,還有其他Python支持文件打包在一起。所以這個可執行文件中已經有了 Python環境,不需要機器本身自帶環境了。

2.3.4 Future Possibility

  • 也許會有直接把Python代碼編譯成 機器代碼
  • 也許會有新的 byte code格式
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章