Jika Python ditafsirkan, apakah file .pyc?

1084

Saya telah diberikan untuk memahami bahwa Python adalah bahasa yang ditafsirkan ...
Namun, ketika saya melihat kode sumber Python saya melihat .pycfile, yang Windows mengidentifikasi sebagai "Compiled Python Files".

Di mana ini masuk?

froadie
sumber
3
Lihat stackoverflow.com/questions/11433579/... untuk justifikasi. Dalam satu kata: kecepatan.
user7610
Apakah itu berarti bahwa bahkan python memiliki 'Tulis sekali, jalankan di mana saja' seperti Java.?
Mrak Vladar
2
@MrakVladar Bahkan Java adalah "Menulis sekali, jalankan di mana saja [bahwa Anda memiliki JVM]". Python tidak berbeda; itu "dijalankan di mana pun Anda memiliki mesin virtual Python". Perbedaan besar adalah bahwa kebanyakan implementasi Python menggabungkan compiler dan interpreter menjadi satu yang dapat dieksekusi, daripada memisahkannya seperti javadan javac.
chepner

Jawaban:

661

Mereka mengandung kode byte , yang merupakan kompilasi dari sumber interpreter Python. Kode ini kemudian dieksekusi oleh mesin virtual Python.

Dokumentasi Python menjelaskan definisi seperti ini:

Python adalah bahasa yang ditafsirkan, sebagai lawan dari bahasa yang dikompilasi, meskipun perbedaannya bisa kabur karena keberadaan kompiler bytecode. Ini berarti bahwa file sumber dapat dijalankan secara langsung tanpa secara eksplisit membuat executable yang kemudian dijalankan.

beristirahat
sumber
10
Menarik, terima kasih. Jadi apakah Python dianggap sebagai bahasa yang ditafsirkan murni?
froadie
194
@froadie: bahasa tidak "ditafsirkan" atau "dikompilasi". SEBUAH implementasi khusus dapat menjadi juru atau compiler (atau hibrida atau compiler JIT).
Joachim Sauer
30
Satu tes 'dikompilasi': apakah ini dikompilasi dengan instruksi mesin yang sebenarnya? Bytecode Python bukan instruksi mesin, dan juga instruksi Java 'JVM', jadi tidak satu pun dari bahasa ini dikompilasi oleh definisi itu. Tetapi keduanya 'dikompilasi' ke kode 'mesin abstrak' perantara, dan keduanya jauh, lebih cepat daripada menjalankan program dengan kurang lebih secara langsung menginterpretasikan kode sumber (yang dilakukan oleh BASIC old-school).
Greggo
20
Menjadi bertele-tele, 'disusun' berarti 'diterjemahkan'. Python kemudian dikompilasi ke bytecode. AFAIK, hanya Bash yang benar - benar ditafsirkan, semua bahasa "ditafsirkan" populer lainnya semua dikompilasi ke bytecode.
bfontaine
13
Sebenarnya, mereka adalah instruksi mesin, hanya bukan instruksi mesin asli untuk CPU fisik host. Karena itu mengapa kita menyebutnya VM? Seperti bahasa Esperanto untuk bahasa assembly. Saat ini kami bahkan memiliki kode asli untuk CPU fiksi (tetapi masih ditiru) (upaya Mojang untuk membuat anak-anak tertarik). Rexx telah (atau bisa) benar-benar ditafsirkan, dan BAT dan CMD (dan DCL) ditafsirkan.
mckenzm
994

Saya telah diberikan untuk memahami bahwa Python adalah bahasa yang ditafsirkan ...

Meme populer ini tidak benar, atau, lebih tepatnya, dibangun di atas kesalahpahaman tingkat bahasa (alami): kesalahan yang sama akan mengatakan "Alkitab adalah buku hardcover". Biarkan saya jelaskan perumpamaan itu ...

"Alkitab" adalah "sebuah buku" dalam arti menjadi kelas dari (sebenarnya, objek fisik yang diidentifikasi sebagai) buku; buku-buku yang diidentifikasi sebagai "salinan Alkitab" seharusnya memiliki kesamaan yang mendasar (isinya, meskipun bahkan bisa dalam bahasa yang berbeda, dengan terjemahan yang dapat diterima berbeda, tingkat catatan kaki dan anotasi lainnya) - namun, buku-buku itu adalah sangat diizinkan untuk berbeda dalam banyak aspek yang tidak dianggap mendasar - jenis penjilidan, warna penjilidan, font yang digunakan dalam pencetakan, ilustrasi jika ada, margin yang dapat ditulis atau tidak, jumlah dan jenis penanda bawaan , dan sebagainya, dan sebagainya.

Sangat mungkin bahwa pencetakan Alkitab yang khas tentu saja akan mengikat hardcover - setelah semua, itu adalah buku yang biasanya dimaksudkan untuk dibaca berulang-ulang, di-bookmark di beberapa tempat, dibolak-balik mencari petunjuk bab dan ayat yang diberikan , dll, dll, dan penjilidan hardcover yang baik dapat membuat salinan yang diberikan bertahan lebih lama saat digunakan. Namun, ini adalah masalah duniawi (praktis) yang tidak dapat digunakan untuk menentukan apakah objek buku yang sebenarnya adalah salinan Alkitab atau tidak: cetakan paperback sangat mungkin!

Demikian pula, Python adalah "bahasa" dalam arti mendefinisikan kelas implementasi bahasa yang semuanya harus serupa dalam beberapa hal mendasar (sintaksis, sebagian besar semantik kecuali bagian-bagian yang secara eksplisit diizinkan berbeda) tetapi diizinkan sepenuhnya berbeda dalam setiap detail "implementasi" - termasuk bagaimana mereka berurusan dengan file sumber yang diberikan, apakah mereka mengkompilasi sumber ke beberapa formulir tingkat yang lebih rendah (dan, jika demikian, bentuk mana - dan apakah mereka menyimpannya formulir yang dikompilasi, ke disk atau tempat lain), bagaimana mereka mengeksekusi formulir tersebut, dan sebagainya.

Implementasi klasik, CPython, sering disebut hanya "Python" singkatnya - tetapi itu hanya salah satu dari beberapa implementasi kualitas produksi, berdampingan dengan IronPython Microsoft (yang mengkompilasi ke kode CLR, yaitu, ".NET"), Jython (yang mengkompilasi kode JVM), PyPy (yang ditulis dengan Python sendiri dan dapat dikompilasi ke berbagai macam bentuk "back-end" termasuk "just-in-time" bahasa mesin yang dihasilkan). Mereka semua adalah Python (== "implementasi bahasa Python") sama seperti banyak objek buku yang berbeda-beda semua bisa menjadi Alkitab (== "salinan Alkitab").

Jika Anda tertarik pada CPython secara spesifik: ia mengkompilasi file sumber ke dalam bentuk tingkat rendah spesifik-Python (dikenal sebagai "bytecode"), melakukannya secara otomatis ketika diperlukan (ketika tidak ada file bytecode yang sesuai dengan file sumber, atau file bytecode lebih tua dari sumber atau dikompilasi oleh versi Python yang berbeda), biasanya menyimpan file bytecode ke disk (untuk menghindari kompilasi ulang mereka di masa depan). OTOH IronPython biasanya akan dikompilasi ke kode CLR (menyimpannya ke disk atau tidak, tergantung) dan Jython ke kode JVM (menyimpannya ke disk atau tidak - itu akan menggunakan .classekstensi jika itu menyimpannya).

Bentuk-bentuk tingkat yang lebih rendah ini kemudian dijalankan oleh "mesin virtual" yang sesuai juga dikenal sebagai "juru bahasa" - VM CPython, runtime .Net, Java VM (alias JVM), yang sesuai.

Jadi, dalam pengertian ini (apa yang dilakukan implementasi tipikal), Python adalah "bahasa yang diartikan" jika dan hanya jika C # dan Java adalah: semuanya memiliki strategi implementasi yang khas untuk menghasilkan bytecode terlebih dahulu, kemudian menjalankannya melalui VM / interpreter .

Lebih mungkin fokusnya adalah pada seberapa "berat", lambat, dan tinggi upacara proses kompilasi. CPython dirancang untuk mengkompilasi secepat mungkin, seringan mungkin, dengan upacara sesedikit mungkin - kompiler melakukan pengecekan dan optimasi kesalahan yang sangat sedikit, sehingga dapat berjalan cepat dan dalam jumlah kecil memori, yang pada gilirannya memungkinkannya dijalankan secara otomatis dan transparan kapan pun diperlukan, tanpa pengguna bahkan perlu menyadari bahwa ada kompilasi yang terjadi, sebagian besar waktu. Java dan C # biasanya menerima lebih banyak pekerjaan selama kompilasi (dan karenanya tidak melakukan kompilasi otomatis) untuk memeriksa kesalahan lebih menyeluruh dan melakukan lebih banyak optimasi. Ini adalah rangkaian skala abu-abu, bukan situasi hitam atau putih,

Alex Martelli
sumber
2
Jawaban yang indah Hanya koreksi kecil ke paragraf terakhir: Python dirancang untuk mengkompilasi secepat mungkin (dll.). Kali ini benar-benar bahasa, dengan kurangnya sistem jenis statis dan hal-hal Ketika orang berbicara tentang bahasa "ditafsirkan", mereka biasanya berarti bahasa "dinamis".
Elazar
2
@ Elazar, sebenarnya, implementasi lain dari Python, seperti PyPy, yang tidak terburu-buru untuk mengkompilasi, berhasil melakukan analisis yang lebih menyeluruh yang diperlukan oleh kurangnya pengetikan statis dan menghasilkan kompilasi tepat waktu ke kode mesin (sehingga mempercepat program yang sudah berjalan lama beberapa kali).
Alex Martelli
Di mana Cython cocok di sini? Apakah Anda menganggapnya bahasa yang berbeda atau itu implementasi Python? Juga, apakah ini meme "ditafsirkan" vs dikompilasi mungkin hanya sebuah terminologi kebingungan karena Python VM sering disebut sebagai "penerjemah" nya? Akan sama validnya untuk memanggil JVM atau .NET runtime interpreter. Mereka berdua kebanyakan menerjemahkan bytecode ke dalam kode mesin JIT (dengan beberapa pengecualian optimasi caching)
Davos
181

Tidak ada bahasa yang ditafsirkan. Apakah penerjemah atau kompiler digunakan adalah murni sifat implementasi dan sama sekali tidak ada hubungannya dengan bahasa.

Setiap bahasa dapat diimplementasikan oleh penerjemah atau kompiler. Sebagian besar bahasa memiliki setidaknya satu implementasi dari setiap jenis. (Misalnya, ada penerjemah untuk C dan C ++ dan ada kompiler untuk JavaScript, PHP, Perl, Python, dan Ruby.) Selain itu, sebagian besar implementasi bahasa modern sebenarnya menggabungkan juru bahasa dan kompiler (atau bahkan beberapa kompiler).

Bahasa hanyalah seperangkat aturan matematika abstrak. Seorang juru bahasa adalah salah satu dari beberapa strategi implementasi konkret untuk suatu bahasa. Keduanya hidup pada level abstraksi yang sangat berbeda. Jika bahasa Inggris adalah bahasa yang diketik, istilah "bahasa yang ditafsirkan" akan menjadi kesalahan ketik. Pernyataan "Python adalah bahasa yang ditafsirkan" bukan hanya salah (karena salah akan menyiratkan bahwa pernyataan itu bahkan masuk akal, bahkan jika itu salah), itu hanya tidak masuk akal , karena bahasa tidak pernah dapat didefinisikan sebagai "ditafsirkan."

Secara khusus, jika Anda melihat implementasi Python yang ada saat ini, ini adalah strategi implementasi yang mereka gunakan:

  • IronPython: kompilasi ke pohon DLR yang kemudian DLR dikompilasi ke bytecode CIL. Apa yang terjadi pada bytecode CIL tergantung pada CLI VES yang Anda jalankan, tetapi Microsoft .NET, GNU Portable.NET dan Novell Mono pada akhirnya akan mengkompilasinya ke kode mesin asli.
  • Jython: menafsirkan kode sumber Python sampai mengidentifikasi jalur kode panas, yang kemudian dikompilasi ke bytecode JVML. Apa yang terjadi pada bytecode JVML tergantung pada JVM yang Anda jalankan. Maxine akan langsung mengompilasinya ke kode asli yang tidak dioptimalkan hingga mengidentifikasi jalur kode panas, yang kemudian dikompilasi ulang menjadi kode asli yang dioptimalkan. HotSpot pertama-tama akan menafsirkan bytecode JVML dan kemudian mengkompilasi jalur kode panas untuk kode mesin yang dioptimalkan.
  • PyPy: mengkompilasi ke bytecode PyPy, yang kemudian akan ditafsirkan oleh VM PyPy sampai mengidentifikasi jalur kode panas yang kemudian dikompilasi ke dalam kode asli, bytecode JVML atau bytecode CIL tergantung pada platform yang Anda jalankan.
  • CPython: mengkompilasi ke bytecode CPython yang kemudian diinterpretasikan.
  • Stackless Python: mengkompilasi bytecode CPython yang kemudian diinterpretasikan.
  • Unladen Swallow: mengkompilasi ke bytecode CPython yang kemudian ditafsirkan hingga mengidentifikasi jalur kode panas yang kemudian dikompilasi ke LLVM IR yang kemudian dikompilasi oleh kompilator LLVM ke kode mesin asli.
  • Cython: mengkompilasi kode Python ke kode C portabel, yang kemudian dikompilasi dengan kompiler C standar
  • Nuitka: mengkompilasi kode Python ke kode C ++ yang bergantung pada mesin, yang kemudian dikompilasi dengan kompiler C standar

Anda mungkin memperhatikan bahwa setiap implementasi dalam daftar itu (ditambah beberapa lainnya yang tidak saya sebutkan, seperti tinypy, Shedskin atau Psyco) memiliki kompiler. Bahkan, sejauh yang saya tahu, saat ini tidak ada implementasi Python yang murni ditafsirkan, tidak ada implementasi yang direncanakan dan tidak pernah ada implementasi seperti itu.

Tidak hanya istilah "bahasa yang ditafsirkan" tidak masuk akal, bahkan jika Anda menafsirkannya sebagai "bahasa dengan implementasi yang ditafsirkan", itu jelas tidak benar. Siapa pun yang memberi tahu Anda hal itu, jelas tidak tahu apa yang ia bicarakan.

Secara khusus, .pycfile yang Anda lihat adalah file bytecode di-cache yang dihasilkan oleh CPython, Stackless Python atau Unladen Swallow.

Jörg W Mittag
sumber
5
Dasar sekolah tua seperti MSBASIC tidak memiliki bentuk peralihan. Program ini ditafsirkan langsung dari bentuk sumber (atau sumber dekat, suatu bentuk di mana kata kunci diwakili oleh token 1-byte, dan baris # dengan biner int 2-byte, tetapi sisanya hanya ASCII). Jadi sebenarnya 'goto' akan membutuhkan jumlah waktu yang berbeda tergantung pada berapa banyak baris sumber yang harus dicari untuk mencari tujuan yang cocok. Ekspresi seperti * b-2 * cos (x) secara efektif di-parsing setiap kali dieksekusi.
greggo
4
@greggo: Dan jika Anda ingin lebih lama lagi, versi asli BASIC adalah kompiler kode asli. Ini harus membuktikan betapa konyolnya gagasan bahasa "dikompilasi" atau "ditafsirkan".
Jörg W Mittag
Terima kasih telah menjelaskan bagaimana berbagai kompiler / penerjemah python berperilaku. Saya bertanya-tanya apakah ada kompiler Python yang baik yang menghasilkan C atau JavaScript yang efisien. Tampaknya sangat bisa dilakukan, mungkin bukan untuk konsumsi massal, tetapi untuk subset yang wajar dari Python setidaknya. Saya juga ingin tahu apa itu Cython.
personal_cloud
Cython disebutkan dalam SciPy 2009, tetapi saya dapat memaafkan Anda karena tidak mengetahuinya kembali pada tahun 2010 (di sini saya pada tahun 2017 baru saja mempelajarinya). Tetap kita harus menemukan contoh JavaScript ... Jython tidak masuk akal bagi saya (bukankah Java sudah mati pada 2009? Yah hmm, mungkin tidak ... C ++ boost tidak terlalu bagus saat itu)
personal_cloud
1
@personal_cloud: Saya tidak cukup mengikuti komentar Anda. Ya, tentu saja, saya tahu tentang Cython, tetapi apa hubungannya dengan apa pun? Ini bukan implementasi dari Python, ini adalah bahasa yang sama sekali berbeda. Juga, benar-benar tidak sulit untuk menemukan contoh JavaScript, pada kenyataannya, semua implementasi JavaScript arus utama yang ada memiliki kompiler. Terakhir, Jython adalah implementasi dari Python sama seperti implementasi lainnya dari Python. Dan itu adalah implementasi bahasa pada platform Java sama seperti implementasi bahasa lainnya pada platform Java.
Jörg W Mittag
61

Ini dibuat oleh interpreter Python ketika .pyfile diimpor, dan mereka berisi "dikompilasi bytecode" dari modul / program yang diimpor, idenya adalah bahwa "terjemahan" dari kode sumber ke bytecode (yang hanya perlu dilakukan sekali) dapat dilewati pada imports berikutnya jika .pyclebih baru dari .pyfile yang sesuai , sehingga mempercepat startup. Tapi itu masih ditafsirkan.

Tim Pietzcker
sumber
10
Benar. Kecuali banyak pustaka Python inti yang ditulis dalam C. Jadi, bagian dari proses python diinterpretasikan, sebagian dijalankan dalam C. Anda dapat melakukan hal yang sama terhadap bit kode sensitif kinerja Anda sendiri.
bwawok
44

Untuk mempercepat memuat modul, Python cache konten yang dikompilasi modul dalam .pyc.

CPython mengkompilasi kode sumbernya menjadi "kode byte", dan untuk alasan kinerja, kode cache ini disimpan dalam sistem file setiap kali file sumber mengalami perubahan. Ini membuat pemuatan modul Python lebih cepat karena fase kompilasi dapat dilewati. Ketika file sumber Anda adalah foo.py, CPython membuat cache kode byte dalam file foo.pyc tepat di sebelah sumber.

Dalam python3, mesin impor Python diperluas untuk menulis dan mencari file cache kode byte dalam satu direktori di dalam setiap direktori paket Python. Direktori ini akan disebut __pycache__.

Berikut adalah bagan alur yang menjelaskan bagaimana modul dimuat:

masukkan deskripsi gambar di sini

Untuk informasi lebih lanjut:

ref: PEP3147
ref: File Python "Dikompilasi"

hxysayhi
sumber
38

INI UNTUK PEMULA,

Python secara otomatis mengkompilasi skrip Anda ke kode yang dikompilasi, yang disebut kode byte, sebelum menjalankannya.

Menjalankan skrip tidak dianggap sebagai impor dan no .pyc akan dibuat.

Misalnya, jika Anda memiliki file skrip abc.py yang mengimpor modul lain xyz.py , saat Anda menjalankan abc.py , xyz.pyc akan dibuat sejak xyz diimpor, tetapi tidak ada file abc.pyc yang akan dibuat sejak abc. py tidak diimpor.

Jika Anda perlu membuat file .pyc untuk modul yang tidak diimpor, Anda dapat menggunakan py_compiledan compileallmodul.

The py_compilemodul dapat secara manual mengkompilasi modul apapun. Salah satu caranya adalah dengan menggunakan py_compile.compilefungsi dalam modul itu secara interaktif:

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

Ini akan menulis .pyc ke lokasi yang sama dengan abc.py (Anda dapat menimpanya dengan parameter opsional cfile).

Anda juga dapat secara otomatis mengkompilasi semua file dalam direktori atau direktori menggunakan modul compileall.

python -m compileall

Jika nama direktori (direktori saat ini dalam contoh ini) dihilangkan, modul mengkompilasi semua yang ditemukan sys.path

MAX
sumber
6
dan apa manfaat kompilasi untuk mendapatkan abc.py?
Saher Ahwal
@ SaherAhwal Satu manfaat yang bisa saya pikirkan adalah memeriksa sintaks.
Yi Bao
20

Python (setidaknya implementasi yang paling umum dari itu) mengikuti pola kompilasi sumber asli ke kode byte, kemudian menafsirkan kode byte pada mesin virtual. Ini berarti (sekali lagi, implementasi yang paling umum) bukanlah penerjemah murni atau kompilator murni.

Sisi lain dari ini adalah, bagaimanapun, bahwa proses kompilasi sebagian besar disembunyikan - file .pyc pada dasarnya diperlakukan seperti cache; mereka mempercepat, tetapi Anda biasanya tidak harus menyadarinya sama sekali. Secara otomatis membatalkan dan memuatnya kembali (kompilasi ulang kode sumber) bila perlu berdasarkan waktu file / tanggal perangko.

Satu-satunya saat saya melihat masalah dengan ini adalah ketika file bytecode yang dikompilasi entah bagaimana mendapat cap waktu di masa depan, yang berarti selalu terlihat lebih baru daripada file sumber. Karena terlihat lebih baru, file sumber tidak pernah dikompilasi ulang, jadi apa pun perubahan yang Anda buat, mereka diabaikan ...

Jerry Coffin
sumber
12

File * .py Python hanyalah file teks tempat Anda menulis beberapa baris kode. Saat Anda mencoba menjalankan file ini menggunakan say "python filename.py"

Perintah ini memanggil Python Virtual Machine. Python Virtual Machine memiliki 2 komponen: "compiler" dan "interpreter". Penerjemah tidak dapat langsung membaca teks dalam file * .py, jadi teks ini pertama-tama dikonversi menjadi kode byte yang ditargetkan ke PVM (bukan perangkat keras tetapi PVM) . PVM mengeksekusi kode byte ini. * .pyc file juga dihasilkan, sebagai bagian dari menjalankannya yang melakukan operasi impor Anda pada file di shell atau di beberapa file lainnya.

Jika file * .pyc ini sudah dibuat maka setiap kali Anda menjalankan / mengeksekusi file * .py Anda, sistem secara langsung memuat file * .pyc Anda yang tidak memerlukan kompilasi apa pun (Ini akan menghemat beberapa siklus mesin prosesor).

Setelah file * .pyc dibuat, tidak perlu lagi file * .py, kecuali Anda mengeditnya.

Vishal Mopari
sumber
7

Kode python melewati 2 tahap. Langkah pertama mengkompilasi kode menjadi file .pyc yang sebenarnya merupakan bytecode. Maka file .pyc ini (bytecode) ditafsirkan menggunakan juru bahasa CPython. Silakan merujuk ke tautan ini . Di sini proses kompilasi dan eksekusi kode dijelaskan dengan istilah yang mudah.

Tango
sumber