CPython & .pyc & Bytecode Nedir?
5 min read

CPython & .pyc & Bytecode Nedir?

CPython & .pyc & Bytecode Nedir?

Python programlama dili için direkt yorumlayıcılı ve derleyicili bir dildir diyenleri duymuşsunuzdur. Bu iki ifade de doğrudur ama eksiktir. Çünkü Python yorumlayıcısı olan bir dildir fakat bu yorumlayıcı önce Python kodlarını derleyerek sanal makinenin okuyacağı bir ara koda dönüştürür. İşte bu iki aşamalı sistem Python yorumlayıcıları sayesinde gerçekleştirilir.

Python kodlarımızın ekrana çıktı olarak yansıtılması sürecinde birçok ara eleman rol alır. Bunlardan bazıları Cpython, pyc ve bytecode’dur. Bu dersimizde ise daha bilinçli ve bilgili bir Python kullanıcısı olabilmek adına bu elemanların ne işe yaradıklarını anlamaya çalışacağız.

Cpython Nedir?

CPython, standart Python yorumlayıcısıdır (Interpreter) ve Python.org üzerinden indirilebilir. Yani yazdığımız .py uzantılı dosyaların içindeki kodların kabuk ile etkileşime girmesini sağlayan bytecode’larını üretir ve bu kodlar sanal makinede çalıştırılır. Bytecode, makine kodu değildir, sanal makine kodudur.

Diğer Python Yorumlayıcıları;

  • CPython.
  • IronPython.
  • Jython.
  • PyPy.
  • PythonNet.
  • Stackless Python.
569x312

Şemada gördüğünüz gibi elinizdeki bir .py uzantılı dosya CPython gibi yorumlayıcılar ile önce derlenerek sanal makinenin çalıştırabileceği bytecode’a çevrilir. Ardından sanal makine bu bytecode’u okuyarak çalıştırır ve kullanıcıya çıktı sunar.

.pyc Nedir?

Yukarıda ki girişte Cpython’ın bir yorumlayıcı olduğunu öğrendik. Şimdi ise Cpython ile Python sanal makinesinin okuyabilmesi için önce derlenen bir .py dosyasının bytecode‘a çevrilmesi ile oluşan .pyc uzantısını inceleyeceğiz.

Biraz karışık oldu ama özetle bir .pyc dosyası bytecode‘dir. Bu bytecode ise Python yorumlayıcısı tarafından sanal makinenin okuyabilmesi için .py den derlenerek oluşturulmuştur. Özetle, derlenmiş python dosyalarının uzantısıdır.

597x303

Bu evrimi daha iyi anlayabilmek ve biraz sonra yapacağımız örneklerin daha iyi oturması için öncelikle bytecode nedir daha iyi öğrenelim.

bytecode Nedir?

Bir konuyu öğrenirken birçok kavram birbirine karışmaya başlıyor. Bunun önüne geçebilmek için biraz daha temele inersek karşımıza bytecode çıkıyor. Çünkü pyc konusunu anlatırken Python yorumlayıcısının yazdığımız kodları bir bytecode’a çevirdiğini söyledik. Öyleyse nedir bu bytecode?

Bytecode, basit tabiriyle bir program kodudur (pseudo code). Nasıl assembly kodları okunabilir bir programlama diliyse, bytecode de aynı assembly gibi sanal makinelerin okuyabilmesi için oluşturulan bir koddur ve binary dosyasıdır (dosyayı binary editörler ile açtığınızda binary ifadeleri göreceksinizdir). Küçük bir kıyaslamayala bu kavramı tam olarak oturtalım.

944x254

Resimde de gördüğünüz gibi bytecode bir program kodudur ve Sanal makinelerin anlaması için oluşturulur. Sanal makineler ise bytecode u okuyarak makine diline çevirir. Birçokfarklı bytecode syntax‘ı mevcuttur. Örneğin Java sanal makinesinin okuyabilmesi için derlenen bytecode ile Python sanal makinesinin okuyabilmesi için derlenen bytecode’u karşılaştırırsanız sytnaxlarının farklı olduğunu görürsünüz.

!! Unutmayınız: Bir bytecode Java, Python gibi dillerin sanal makineleri tarafından kullanılırken makine kodu donanım (CPU) tarafından kullanılır.

Yazdığımız bir programın oluşan bytecode dosyasını okuyabilmemiz için Python içinde dis - Python Bytecode Disassembler modülü vardır. Binary dosya olan bytecode‘u direkt açarak okuyamayacağımız için dis modülünü kullanarak okunabilir bir bytecode elde ederiz ve kodlama hakkında fikir sahibi olabilir, geliştirme yapabiliriz.

Test için öncelikle kerteriz.py isimli bir dosya oluşturup içine basit bir kod yazalım.

print("Merhaba Kerteriz Blog")

Şimdi ise python -m dis kerteriz.py komutunu çalıştırarak bytecode’muzun okunabilir bir halini görelim.

565x169

Resimde görüldüğü gibi Python yorumlayıcısı tarafından oluşturulan bytecode’un okunabilir bir halini ekrana basmış olduk. Eğer ham kodunuz üzerinden değil de elinizdeki .pyc uzantılı bytecode üzerinden okunabilir halde bytecode elde etmek istiyorsanız bu sefer aşağıda ki kodları kullanabilirsiniz.

import dis
import marshal

with open('kerteriz.pyc', 'rb') as f:
    f.seek(16)
    dis.dis(marshal.load(f))

!! Burada ki f.seek(16) bölümü Python 3.7 sürümünde verinin başındaki 16bayt uzunluğundaki marshal versiyon numarasını, düzenleme tarihi (timestamp) ve marshal methodunu içeren header kısmını kaldırmak içindir. Bu uzunluk eğer Python 3.0 ve Python 3.6 arası bir versiyon kullanırsanız 12, Python 2.x kullanıyorsanız 8 olmalıdır. Daha fazla bilgi için şuradaki ve şuradaki makaleyi inceleyebilirsiniz.

.py ve .pyc Farkı

Yazdığınız bir .py uzantılı Python dosyası ve bu dosyadan derlenerek oluşturulan .pyc (Derlenmiş Python Dosyası) dosyası çalıştırıldığında birebir aynı sonuçları verirler. Çünkü yazdığınız program aynıdır. Sadece .py Python programlama dosyasıyken .pyc sanal makinenin okuyabilmesi için oluşturulan derlenmiş bir Python dosyası yani bytecode‘dir.

Eğer bir dizinde hem .py hemde .pyc uzantılı dosya varsa Python öncelikle .pyc uzantılı dosyayı çağırır. Fakat .pyc oluşturduktan sonra .py dosyanızda bir değişiklik yaptıysanız Python her iki dosyanın da oluşturulma zamanına bakar ve daha yeni olan dosyayı çalıştırır. Bu durumda .py uzantılı dosya çalıştırılır.

Küçük bir örnekle her iki kavramı kıyaslayalım. Öncelikle kerteriz.py isimli dosyamıza basit bir Python kodu yazalım.

print("Merhaba Kerteriz Blog Sakinleri!")

Şimdi bu .py dosyasını .pyc dosyasına çevirelim. Bunun için dosyamızın olduğu dizine gidelim ve aşağıdaki komut ile dizinde bulunan .py uzantılı dosyaları .pyc uzantısına çevirelim.

python -m compileall

Komutu çalıştırdığınızda .py dosyanızın olduğu dizinde yeni bir _ _pycache_ _ klasörü ve bu klasörün içinde .pyc uzantılı dosya oluştuğunu göreceksiniz. Ekran çıktımız ise şu şekilde olacaktır.

677x267

Yukarıdaki komutu direkt dosya adı belirterek te kullanabilirsiniz.

python -m py_compile kerteriz.py

Şimdi her iki dosyayı da çalıştıralım.

368x135

Gördüğünüz gibi her iki dosyada aynı sonucu veriyor. Aradaki tek fark .pyc dosyası zaten derlenmiş bir Python dosyası olduğu için bir kere daha derlenmeye ihtiyacı yoktur ve .py dosyasına göre çağrılma süresi daha hızlıdır.

!! NOT: pyc dosyalarının py dosyalarından daha hızlı çalıştığı yanlış bir ifadedir. pyc dosyaları sadece daha hızlı çağrılır. Bu ise çok büyük bir farka tekabül etmez. Eğer Python kodlarınızı hızlandırmak istiyorsanız Cython kullanabilirsiniz. (İleride işleyeceğiz)