CPython, Bytecode ve Python Virtual Machine (PVM)
Python öğrenen çoğu geliştirici şu aşamaya kadar gelir:
x = 10
y = 20
print(x + y)
Kod çalışır, sonuç gelir ve konu kapanır.
Fakat profesyonel seviyede Python geliştiren, performans optimizasyonu yapan veya Python'un iç mimarisini anlamak isteyen bir yazılımcının aşağıdaki üç kavramı çok iyi bilmesi gerekir:
- CPython
- Bytecode
- Python Virtual Machine (PVM)
Bu üçü Python'un çalışma motorunu oluşturur.
Büyük Resim
Bir Python programı çalıştırıldığında süreç şu şekildedir:
Python Source Code
↓
Tokenizer
↓
Parser
↓
AST
↓
Compiler
↓
Bytecode
↓
Python Virtual Machine
↓
CPython Runtime
↓
Operating System
↓
CPU
Buradaki en kritik bölüm:
Bytecode
↓
PVM
çiftidir.
1. CPython Nedir?
Öncelikle çok önemli bir yanlış anlaşılmayı düzeltelim.
Birçok kişi Python'u bir dil zanneder.
Aslında:
Python = Dil Spesifikasyonu
CPython ise:
Python'un en yaygın implementasyonu
dur.
Python Bir Dil Tanımıdır
Nasıl ki:
C#
Java
JavaScript
bir dil tanımıysa,
Python da bir dil tanımıdır.
Bu tanımı çalıştıran farklı motorlar vardır.
Örneğin:
| Implementasyon | Dil |
|---|---|
| CPython | Python |
| PyPy | Python |
| Jython | Python |
| IronPython | Python |
| MicroPython | Python |
Hepsi Python kodu çalıştırır.
Ama iç yapıları farklıdır.
CPython Nedir?
CPython:
C dili ile yazılmış Python yorumlayıcısıdır.
Python.org üzerinden indirdiğiniz standart Python budur.
Örneğin:
python app.py
komutu verdiğinizde çalışan şey CPython'dur.
CPython'ın kaynak kodu yaklaşık:
500.000+ satır C
içerir.
Kaynak kodu:
CPython'ın Görevi
CPython:
x = 10
y = 20
print(x + y)
kodunu alır.
Sonra:
Token
↓
AST
↓
Bytecode
↓
PVM Execution
işlemlerini gerçekleştirir.
CPython İçindeki Bileşenler
Basitleştirilmiş görünüm:
CPython
│
├── Lexer
├── Parser
├── Compiler
├── Bytecode Generator
├── PVM
├── Garbage Collector
├── Memory Manager
└── C API
2. Bytecode Nedir?
Python doğrudan makine koduna çevrilmez.
Java'da olduğu gibi ara bir temsil oluşturulur.
Buna:
Bytecode
denir.
Örnek
Kodumuz:
x = 10
y = 20
z = x + y
olsun.
Python bunu aşağıdakine benzer bytecode'a dönüştürür:
LOAD_CONST 10
STORE_NAME x
LOAD_CONST 20
STORE_NAME y
LOAD_NAME x
LOAD_NAME y
BINARY_ADD
STORE_NAME z
Bytecode'un Amacı
Python'un şu kodu:
x + y
işlemciye doğrudan gönderilemez.
Çünkü CPU şunu anlamaz:
x
+
y
Bu nedenle Python önce bunu standart komutlara dönüştürür.
Bytecode Nasıl Görülür?
Python'da:
import dis
def test():
x = 10
y = 20
return x + y
dis.dis(test)
çıktı:
LOAD_CONST 10
STORE_FAST x
LOAD_CONST 20
STORE_FAST y
LOAD_FAST x
LOAD_FAST y
BINARY_OP +
RETURN_VALUE
şeklinde olur.
.pyc Dosyaları
Python bytecode'u diske de yazabilir.
Örneğin:
main.py
çalıştırıldığında:
__pycache__
oluşur.
İçinde:
main.cpython-313.pyc
benzeri dosyalar vardır.
Bu dosya:
Bytecode
saklar.
Neden Saklanır?
Tekrar derleme maliyetini azaltmak için.
İkinci çalıştırmada:
.py
yerine
.pyc
kullanılabilir.
Bu da açılış süresini azaltır.
Bytecode Makine Kodu Mudur?
Hayır.
En çok karıştırılan konu budur.
Bytecode:
LOAD_FAST
STORE_FAST
BINARY_ADD
gibi komutlardan oluşur.
CPU bunları anlayamaz.
Bu komutları çalıştıracak başka bir sistem gerekir.
İşte burada PVM devreye girer.
3. Python Virtual Machine (PVM)
PVM:
Python Bytecode'unu çalıştıran sanal işlemcidir.
Gerçek CPU ile Karşılaştırma
Gerçek CPU:
MOV
ADD
SUB
MUL
gibi komutlar çalıştırır.
PVM ise:
LOAD_FAST
STORE_FAST
CALL_FUNCTION
BINARY_ADD
çalıştırır.
Mantık
Bytecode:
LOAD_FAST x
LOAD_FAST y
BINARY_ADD
üretmiştir.
PVM bunu okur.
Adım 1
LOAD_FAST x
çalışır.
Stack:
10
Adım 2
LOAD_FAST y
çalışır.
Stack:
20
10
Adım 3
BINARY_ADD
çalışır.
Stack:
30
Bu nedenle PVM'e bazen:
Stack Based Virtual Machine
denir.
Stack Mantığı
Örnek:
3 + 5
Bytecode:
LOAD_CONST 3
LOAD_CONST 5
BINARY_ADD
PVM:
PUSH 3
PUSH 5
ADD
mantığıyla çalışır.
PVM Nerede Çalışır?
Aslında PVM ayrı bir program değildir.
CPython'ın içindedir.
Şöyle düşünün:
CPython
│
├── Compiler
├── Bytecode
└── PVM
Yani:
PVM ⊂ CPython
Python Nesneleri PVM İçinde Nasıl Temsil Edilir?
Örneğin:
x = 10
gördüğümüzde:
"10" doğrudan RAM'e yazılmaz.
CPython şu yapıyı oluşturur:
PyLongObject
Basitleştirilmiş hali:
struct {
reference_count;
type;
value;
}
Yani:
10
aslında bir nesnedir.
BINARY_ADD Gerçekte Ne Yapar?
PVM:
BINARY_ADD
gördüğünde:
CPython içindeki C fonksiyonlarını çağırır.
Örneğin:
PyNumber_Add()
Bu fonksiyon:
10 + 20
mi?
"abc" + "def"
mi?
list1 + list2
mi?
kontrol eder.
Sonra uygun işlemi gerçekleştirir.
Garbage Collector Nerede Devreye Girer?
CPython içinde.
Örneğin:
x = [1,2,3]
oluşturuldu.
Daha sonra:
x = None
oldu.
Referans kalmadığında:
Reference Counting
ve
Garbage Collector
mekanizmaları belleği temizler.
Performans Neden Düşük?
Python'un C veya Rust'tan yavaş olmasının temel nedeni budur.
Çünkü:
x + y
ifadesi:
- Nesne kontrolü
- Tip kontrolü
- Referans yönetimi
- Bytecode yürütme
- PVM yorumlama
gibi birçok katmandan geçer.
C dilinde ise:
int z = x + y;
doğrudan makine koduna çevrilir.
CPython, Bytecode ve PVM İlişkisi
Bütün sistemi tek diyagramda özetlersek:
Python Source Code
│
▼
CPython Parser
│
▼
AST
│
▼
Compiler
│
▼
Bytecode
│
▼
Python Virtual Machine
│
▼
CPython Runtime (C)
│
▼
Operating System
│
▼
CPU
│
▼
Machine Code
Özetle:
- CPython, Python'un C ile yazılmış resmi ve en yaygın yorumlayıcısıdır.
- Bytecode, Python kaynak kodunun CPU'dan önceki ara temsilidir.
- PVM (Python Virtual Machine), bytecode'u yorumlayıp çalıştıran sanal işlemcidir.
- PVM, CPython'ın içinde yer alır ve stack tabanlı çalışır.
- Son aşamada CPython'ın C kodları işletim sistemi ve işlemci üzerinden gerçek makine komutlarını yürütür.
Bu üç yapıyı anladığınızda Python artık yalnızca bir programlama dili değil; derleyici teorisi, sanal makineler, işletim sistemleri ve bilgisayar mimarisinin kesişim noktasında çalışan çok katmanlı bir yürütme platformu olarak görünmeye başlar.
Top comments (0)