Python yorumlanırsa, .pyc dosyaları nedir?


1084

Python'un yorumlanmış bir dil
olduğunu anladım ... Ancak, Python kaynak koduma baktığımda .pycWindows'un "Derlenmiş Python Dosyaları" olarak tanımladığı dosyaları görüyorum .

Bunlar nereden geliyor?


3
Gerekçe için stackoverflow.com/questions/11433579/… adresine bakın . Tek kelimeyle: hız.
user7610



Python bile Java gibi 'Bir kez yaz, herhangi bir yerde çalıştır' anlamına mı geliyor?
Mrak Vladar

2
@MrakVladar Java bile "Bir kez yaz, [JVM'niz olduğu her yerde çalıştırın]". Python farklı değil; "Python sanal makinenizin olduğu her yerde çalıştırın". Büyük fark, çoğu Python uygulamasının derleyiciyi ve yorumlayıcıyı, javave gibi ayırmak yerine tek bir yürütülebilir dosyada birleştirmesidir javac.
chepner

Yanıtlar:


660

Bayt kodu içerirler , bu da Python yorumlayıcısının kaynağı derlediği şeydir. Bu kod daha sonra Python'un sanal makinesi tarafından yürütülür.

Python'un belgeleri tanımı şu şekilde açıklar:

Python, derlenmiş dilin aksine yorumlanmış bir dildir, ancak bytecode derleyicisinin varlığı nedeniyle ayrım bulanık olabilir. Bu, kaynak dosyaların daha sonra çalıştırılan bir yürütülebilir dosya oluşturmadan doğrudan çalıştırılabileceği anlamına gelir.


10
İlginç, teşekkürler. Python tamamen yorumlanmış bir dil olarak mı görülüyor?
froadie

194
@froadie: bir dil bu şekilde "yorumlanmaz" veya "derlenmez". Bir özel uygulama bir yorumlayıcı veya derleyici (veya bir melez veya tam zamanında derleyici) olabilir.
Joachim Sauer

30
Bir 'derlenmiş' testi: gerçek makine talimatları için derlenmiş mi? Python bayt kodu makine talimatları değildir ve Java 'JVM' talimatları da değildir, bu nedenle bu dillerden hiçbiri bu tanım tarafından derlenmez. Ancak her ikisi de bir ara 'soyut makine' koduna 'derlendi' ve her ikisi de, kaynak kodunu (eski okul BASIC'in yaptığı şey) az çok doğrudan yorumlayarak programı çalıştırmaktan çok daha hızlıdır.
greggo

20
Bilgiçlikçi olmak için, 'derlenmiş', 'tercüme edilmiş' anlamına gelir. Python daha sonra bir bayt koduna derlenir . AFAIK, sadece Bash gerçekten yorumlanır, diğer tüm popüler "yorumlanmış" diller bir bayt koduna derlenir.
bfontaine

13
Aslında, onlar olan makine talimatları, sadece değil yerli ana bilgisayarın fiziksel CPU için makine talimatlar. Neden buna VM diyoruz? Gerçekten montaj dili için Esperanto gibi. Günümüzde kurgusal (ama hala taklit edilmiş) CPU'lar (Mojang'ın çocukları ilgilendirme çabası) için yerel kodumuz bile var. Rexx gerçekten yorumlandı (veya yorumlanabilir) ve BAT ve CMD (ve DCL) yorumlandı.
mckenzm

994

Bana Python'un yorumlanmış bir dil olduğunu anlamıştım ...

Bu popüler meme yanlış veya daha doğrusu, (doğal) dil seviyelerinin yanlış anlaşılması üzerine inşa edilmiştir: Benzer bir hata "İncil ciltli bir kitaptır" demek olacaktır. Bu benzetmeyi açıklayayım ...

"İncil" kitapların bir sınıfı (gerçek, fiziksel nesneler olarak tanımlanır) olma anlamında "bir kitap" tır; "İncil'in kopyaları" olarak tanımlanan kitapların ortak bir şeyi olduğu varsayılır (içerikler, farklı dillerde olsalar bile, farklı kabul edilebilir çeviriler, dipnot seviyeleri ve diğer ek açıklamalar) - ancak bu kitaplar mükemmel olmayan birçok açıdan farklılık göstermesine izin verilir. temel olarak kabul - ciltleme türü, ciltleme rengi, baskıda kullanılan yazı tipi (ler), varsa resimler, geniş yazılabilir kenar boşlukları ya da değil, yerleşik yer işaretlerinin sayıları ve türleri ve benzerleri, vb.

İncil'in tipik bir baskısının gerçekten ciltli bir ciltte olması oldukça olasıdır - sonuçta, genellikle tekrar tekrar okunması, çeşitli yerlere işaretlenmesi, verilen bölüm ve ayet işaretçileri aramasıyla başparmaklandırılmış bir kitaptır. , vb. ve iyi ciltli ciltleme, belirli bir kopyanın bu tür kullanım altında daha uzun süre dayanmasını sağlayabilir. Ancak, bunlar verilen bir gerçek kitap nesnesinin İncil'in bir kopyası olup olmadığını belirlemek için kullanılamayan sıradan (pratik) konulardır: ciltsiz baskılar mükemmel bir şekilde mümkündür!

Benzer şekilde, Python, bazı temel açılardan (sözdizimi, açıkça farklılık göstermelerine izin verilenlerin parçaları hariç çoğu anlambilim) benzer olması gereken bir dil uygulamaları sınıfını tanımlamak anlamında "bir dildir". hemen hemen her "uygulama" ayrıntısında - verildikleri kaynak dosyalarla nasıl başa çıktıklarını, kaynakları daha düşük seviyeli formlara (ve eğer öyleyse, hangi formu - derleyip derlemediklerini) ve formları diske veya başka bir yere), söz konusu formları nasıl yürüttüklerini vb.

Klasik uygulamaya, CPython, kısaca sadece "Python" olarak adlandırılır - ancak Microsoft'un IronPython'u (CLR kodlarını derleyen, yani ".NET"), Jython ile yan yana, birkaç üretim kalitesi uygulamasından sadece biri (JVM kodlarıyla derlenir), PyPy (Python'un kendisinde yazılır ve "tam zamanında" üretilen makine dili de dahil olmak üzere çok çeşitli "arka uç" formlarına derlenebilir). Bunların hepsi yüzeysel olarak farklı birçok kitap nesnesinin İncil olabileceği gibi Python (== "Python dilinin uygulamaları"). (== "İncil'in kopyaları").

Özellikle CPython ile ilgileniyorsanız: kaynak dosyaları Python'a özgü alt düzey bir formda derler ("bayt kodu" olarak bilinir), gerektiğinde otomatik olarak yapar (bir kaynak dosyaya karşılık gelen bayt kodu dosyası olmadığında veya bayt kodu dosyası kaynaktan daha eski veya farklı bir Python sürümü tarafından derlenmiş), genellikle bayt kodu dosyalarını diske kaydeder (ileride yeniden derlenmesini önlemek için). OTOH IronPython tipik olarak CLR kodlarını (bunları diske kaydedip kaydetmemeye bağlı olarak) ve Jython'dan JVM kodlarına (bunları diske kaydetme veya kaydetmeme) derler .class.

Bu alt düzey formlar daha sonra "yorumlayıcılar" olarak da bilinen uygun "sanal makineler" tarafından yürütülür - CPython VM, .Net çalışma zamanı, Java VM (diğer adıyla JVM).

Yani, bu anlamda (tipik uygulamalar ne işe yarar), Python yalnızca C # ve Java ise: "önce yorumlanmış bir dildir": hepsinin önce bayt kodu üretmek, ardından bir VM / yorumlayıcı aracılığıyla yürütmek için tipik bir uygulama stratejisi vardır. .

Büyük olasılıkla, derleme sürecinin ne kadar "ağır", yavaş ve yüksek tören olduğuna odaklanılmaktadır. CPython, mümkün olduğu kadar hızlı, mümkün olduğunca az törenle derlemek için tasarlanmıştır - derleyici çok az hata kontrolü ve optimizasyonu yapar, böylece hızlı ve küçük miktarlarda bellek çalıştırabilir, bu da izin verir kullanıcının çoğu zaman bir derleme olduğunu bilmesine bile gerek kalmadan, gerektiğinde otomatik ve şeffaf olarak çalıştırılabilir. Java ve C # genellikle hataları daha kapsamlı bir şekilde kontrol etmek ve daha fazla optimizasyon yapmak için derleme sırasında daha fazla çalışma kabul eder (ve bu nedenle otomatik derleme yapmazlar). Siyah veya beyaz bir durum değil, gri tonların bir sürekliliği,


2
Güzel cevap. Son paragrafa yapılan küçük bir düzeltme: Python , olabildiğince hızlı (vb.) Derlemek üzere tasarlanmıştır. Bu sefer, statik yazı sistemi ve diğer şeylerin eksikliği ile gerçekten dil. İnsanlar "yorumlanmış" diller hakkında konuştuğunda, genellikle "dinamik" diller anlamına gelir.
Elazar

1
@Elazar, aslında, Python'un, derlemek için acele etmeyen PyPy gibi diğer uygulamaları, statik yazım eksikliğinin gerektirdiği daha kapsamlı bir analiz yapmayı başarıyor ve makine koduna tam zamanında derleme üretiyor (böylece hızlanıyor) uzun süredir çalışan programları defalarca).
Alex Martelli

Cython buraya nereye oturuyor? Farklı bir dil mi düşünürsünüz, yoksa bir Python uygulaması mı? Ayrıca, Python VM'sine genellikle "yorumlayıcı" olarak atıfta bulunulduğu için, "yorumlanmış" ve "derlenmiş bir terim" sadece bir terminoloji karışıklığı mıdır? JVM veya .NET çalışma zamanı yorumlayıcılarını çağırmak da geçerli olacaktır. İkisi de çoğunlukla bayt kodunu JIT makine koduna yorumlar (bazı önbellek optimizasyon istisnaları hariç)
Davos

181

Yorumlanmış bir dil diye bir şey yoktur. Bir tercüman veya derleyici kullanılıp kullanılmadığı tamamen uygulamanın bir özelliğidir ve kesinlikle dil ile hiçbir ilgisi yoktur.

Her dil bir tercüman veya derleyici tarafından uygulanabilir. Dillerin büyük çoğunluğunda her türden en az bir uygulama vardır. (Örneğin, C ve C ++ için tercümanlar vardır ve JavaScript, PHP, Perl, Python ve Ruby için derleyiciler vardır.) Ayrıca, modern dil uygulamalarının çoğu hem bir tercümanı hem de bir derleyiciyi (hatta birden çok derleyiciyi) birleştirir.

Bir dil sadece soyut matematiksel kurallar kümesidir. Tercüman, bir dil için somut uygulama stratejilerinden biridir. Bu ikisi tamamen farklı soyutlama seviyelerinde yaşıyorlar. İngilizce yazılan bir dil olsaydı, "yorumlanan dil" terimi bir tür hatası olurdu. "Python yorumlanmış bir dildir" ifadesi sadece yanlış değildir (çünkü yanlış olmak, ifadenin yanlış bile olsa mantıklı olduğunu ima eder), mantıklı değildir , çünkü bir dil hiçbir zaman şu şekilde tanımlanamaz "yorumlanır."

Özellikle, şu anda var olan Python uygulamalarına bakarsanız, bunlar kullandıkları uygulama stratejileridir:

  • IronPython: DLR'nin sonradan CIL bayt koduna derlediği DLR ağaçlarını derler. CIL bayt koduna ne olur, hangi CLI VES üzerinde çalıştığınıza bağlıdır, ancak Microsoft .NET, GNU Portable.NET ve Novell Mono sonunda yerel makine koduna derleyecektir.
  • Jython: Python kaynak kodunu, daha sonra JVML bayt koduna derleyen sıcak kod yollarını tanımlayana kadar yorumlar. JVML bayt koduna ne olacağınız, hangi JVM üzerinde çalıştığınıza bağlıdır. Maxine, sıcak kod yollarını tanımlayana kadar doğrudan optimize edilmemiş yerel koda derler ve daha sonra optimize edilmiş yerel koda yeniden derler. HotSpot önce JVML bayt kodunu yorumlar ve daha sonra etkin kod yollarını optimize edilmiş makine koduna derler.
  • PyPy: PyPy bayt kodunu derler ve daha sonra çalışmakta olduğunuz platforma bağlı olarak yerel koda, JVML bayt koduna veya CIL bayt koduna derlediği sıcak kod yollarını tanımlayana kadar PyPy VM tarafından yorumlanır.
  • CPython: daha sonra yorumladığı CPython bayt kodunu derler.
  • Yığınsız Python: Daha sonra yorumladığı CPython bayt kodunu derler.
  • Yüksüz Yutmak: Daha sonra LLVM derleyicisinin yerel makine koduna derlediği LLVM IR'ye derlediği sıcak kod yollarını tanımlayana kadar yorumladığı CPython bayt kodunu derler.
  • Cython: Python kodunu taşınabilir C koduyla derler ve daha sonra standart C derleyicisiyle derlenir
  • Nuitka: Python kodunu makineye bağlı C ++ koduyla derler ve bu kod daha sonra standart C derleyicisiyle derlenir

Bu listedeki uygulamaların her birinin (artı bahsetmediğim, tinypy, Shedskin veya Psyco gibi bazılarının) bir derleyicisi olduğunu fark edebilirsiniz. Aslında, bildiğim kadarıyla, şu anda tamamen yorumlanmış bir Python uygulaması yoktur, planlanan böyle bir uygulama yoktur ve hiçbir zaman böyle bir uygulama yoktur.

"Tercüme edilmiş dil" terimi sadece anlamlı olmakla kalmaz, aynı zamanda "tercüme edilmiş uygulamalı dil" anlamına da yorumlasanız bile, bu doğru değildir. Kim demişse, açıkçası ne hakkında konuştuğunu bilmiyor.

Özellikle, .pycgördüğünüz dosyalar CPython, Stackless Python veya Unladen Swallow tarafından üretilen önbellek bayt kodu dosyalarıdır.


5
MSBASIC gibi eski okul temellerinin ara formu yoktu. Program doğrudan kaynak formdan (veya kaynağın yakınında, anahtar kelimelerin 1 bayt jetonlarla temsil edildiği bir form ve satır # 'ın 2 baytlık ikili girişler tarafından yorumlandığı, ancak geri kalanı sadece ASCII idi) yorumlandı. Aslında bir 'git', eşleşen hedefi aramak için kaç tane kaynak hattı aramak zorunda olduğuna bağlı olarak farklı miktarlarda zaman alacaktır. * B-2 * cos (x) gibi ifadeler, her yürütüldüğünde etkili bir şekilde yeniden ayrıştırıldı.
greggo

4
@greggo: Ve daha da eski okula gitmek istiyorsanız , BASIC'in orijinal sürümü yerel bir kod derleyicisiydi. Bu, "derlenmiş" veya "yorumlanmış" bir dil kavramının ne kadar gülünç olduğunu kanıtlamalıdır.
Jörg W Mittag

Çeşitli python derleyicilerinin / tercümanlarının nasıl davrandığını açıkladığınız için teşekkür ederiz. Henüz verimli C veya JavaScript üreten iyi Python derleyicileri olup olmadığını merak ediyorum. Çok yapılabilir, belki de toplu tüketim için değil, en azından makul bir Python alt kümesi için. Ayrıca Cython'un ne olduğunu merak ediyorum.
personal_cloud

Cython , SciPy 2009'da bahsedildi, ancak 2010'da bunu bilmediğiniz için sizi affedebilirim (burada 2017'de sadece şimdi öğreniyorum). Yine de bir JavaScript örneği bulmalıyız ... Jython bana bir anlam ifade etmiyor (Java 2009'a kadar ölmemişti mi? Hmm, belki değil ... C ++ artışı o zamanlar o kadar iyi değildi)
personal_cloud

1
@personal_cloud: Yorumunuzu tam olarak takip etmiyorum. Evet, elbette, Cython'u biliyorum, ama bunun herhangi bir şeyle ne ilgisi var? Python'un bir uygulaması değil, tamamen farklı bir dildir. Ayrıca, bir JavaScript örneği bulmak gerçekten zor değil, aslında, şu anda mevcut olan tüm ana JavaScript uygulamalarının derleyicileri var. Son olarak, Jython, Python'un diğer tüm uygulamaları gibi bir Python uygulamasıdır. Java platformundaki diğer dillerdeki uygulamalar gibi, Java platformundaki bir dil uygulamasıdır.
Jörg W Mittag

61

Bunlar, bir .pydosya içe aktarıldığında Python yorumlayıcısı tarafından oluşturulur ve içe aktarılan modülün / programın "derlenmiş bayt kodunu" içerir; buradaki fikir, kaynak koddan bayt koduna "çevirmenin" (yalnızca bir kez yapılması gerekir) karşılık gelen dosyadan daha yeni importise sonraki s'de atlanabilir , böylece başlangıç ​​biraz hızlanır. Ama hala yorumlanıyor..pyc.py


10
Doğru. Birçok temel Python kütüphanesi C'de yazılır. Bu nedenle python koşusunun bir kısmı yorumlanır, bir kısmı C olarak çalışır.
bwawok

44

Modülleri yüklemeyi hızlandırmak için Python, modüllerin derlenmiş içeriğini .pyc'de önbelleğe alır.

CPython kaynak kodunu "bayt kodu" olarak derler ve performans nedenleriyle, kaynak dosya her değiştiğinde bu bayt kodunu dosya sisteminde önbelleğe alır. Bu, derleme aşaması atlanabildiğinden Python modüllerinin yüklenmesini çok daha hızlı hale getirir. Kaynak dosyanız foo.py olduğunda, CPython bayt kodunu kaynağın hemen yanındaki foo.pyc dosyasında önbelleğe alır.

Python3'te, Python'un içe aktarma makineleri, bayt kodu önbellek dosyalarını her Python paket dizininin içindeki tek bir dizinde yazmak ve aramak üzere genişletilir. Bu dizine __pycache__ adı verilecektir.

Modüllerin nasıl yüklendiğini açıklayan bir akış şeması:

resim açıklamasını buraya girin

Daha fazla bilgi için:

ref: PEP3147
ref: “Derlenmiş” Python dosyaları


38

BU BAŞLANGIÇLAR İÇİN,

Python, komut dosyanızı çalıştırmadan önce otomatik olarak bayt kodu adı verilen derlenmiş koda derler.

Bir komut dosyasını çalıştırmak içe aktarma olarak değerlendirilmez ve .pyc oluşturulmaz.

Eğer bir komut dosyası varsa Örneğin, abc.py o ithalatta başka modül xyz.py çalıştırdığınızda, abc.py , xyz.pyc xyz ithal edildiğinden oluşturulacak, ancak hiçbir abc.pyc dosya edilecektir oluşturulan abc beri. py ithal edilmiyor.

İçe aktarılmayan bir modül için bir .pyc dosyası oluşturmanız gerekirse, py_compileve compileallmodüllerini kullanabilirsiniz .

py_compileModül elle herhangi bir modül derlemek olabilir. Bunun bir yolu, py_compile.compilebu modüldeki işlevi etkileşimli olarak kullanmaktır:

>>> import py_compile
>>> py_compile.compile('abc.py')

Bu, .pyc dosyasını abc.py ile aynı konuma yazar (bunu isteğe bağlı parametre ile geçersiz kılabilirsiniz cfile).

Ayrıca compileall modülünü kullanarak bir dizindeki veya dizinlerdeki tüm dosyaları otomatik olarak derleyebilirsiniz.

python -m compileall

Dizin adı (bu örnekteki geçerli dizin) atlanırsa, modül bulunan her şeyi derler sys.path


6
ve abc.py dosyasını elde etmek için derlemenin yararı nedir?
Saher Ahwal

@SaherAhwal Düşünebileceğim bir fayda sözdizimi denetimidir.
Yi Bao

20

Python (en azından en yaygın uygulaması), orijinal kaynağı bayt kodlarına derleme, ardından bayt kodlarını sanal bir makinede yorumlama modelini takip eder. Bunun anlamı (en yaygın uygulama) ne saf bir tercüman ne de saf bir derleyici olmasıdır.

Bununla birlikte, bunun diğer tarafı, derleme işleminin çoğunlukla gizlendiğidir - .pyc dosyaları temel olarak bir önbellek gibi ele alınır; işleri hızlandırırlar, ancak normalde bunların farkında olmanız gerekmez. Dosya zaman / tarih damgalarına göre gerektiğinde bunları otomatik olarak geçersiz kılar ve yeniden yükler (kaynak kodunu yeniden derler).

Bununla ilgili bir sorun gördüğüm tek zaman, derlenmiş bir bayt kodu dosyasının bir şekilde geleceğe iyi bir zaman damgası almasıydı, bu da her zaman kaynak dosyadan daha yeni görünmesi anlamına geliyordu. Daha yeni göründüğünden, kaynak dosya hiçbir zaman yeniden derlenmedi, bu nedenle ne değişiklik yaparsanız yapın göz ardı edildi ...


12

Python'un * .py dosyası sadece bazı kod satırları yazdığınız bir metin dosyasıdır. Bu dosyayı "python dosyaadı.py" deyince çalıştırmayı denediğinizde

Bu komut Python Sanal Makinesi'ni çağırır. Python Virtual Machine'in 2 bileşeni vardır: "derleyici" ve "yorumlayıcı". Yorumlayıcı * .py dosyasındaki metni doğrudan okuyamaz, bu nedenle bu metin önce PVM'yi (donanım değil PVM) hedefleyen bir bayt koduna dönüştürülür . PVM bu bayt kodunu yürütür. * .pyc dosyası ayrıca, kabukta veya başka bir dosyada dosya alma işleminizi gerçekleştiren çalıştırmanın bir parçası olarak oluşturulur.

Bu * .pyc dosyası zaten oluşturulmuşsa, * .py dosyanızı her çalıştırdığınızda / yürüttüğünüzde, sistem herhangi bir derlemeye ihtiyaç duymayan * .pyc dosyanızı doğrudan yükler (Bu işlemcinin bazı makine işlem döngülerini kurtaracaktır).

* .Pyc dosyası oluşturulduktan sonra, düzenlemediğiniz sürece * .py dosyasına gerek yoktur.


7

Python kodu 2 aşamadan geçer. İlk adım, kodu aslında bir bytecode olan .pyc dosyalarında derler. Sonra bu .pyc dosyası (bayt kodu) CPython yorumlayıcısı kullanılarak yorumlanır. Lütfen bu bağlantıya bakın . Burada kod derleme ve yürütme süreci kolay bir şekilde açıklanmaktadır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.