Kapan file .pyc di-refresh?


92

Saya memahami bahwa file ".pyc" adalah versi yang dikompilasi dari file teks biasa ".py", yang dibuat pada waktu proses untuk membuat program berjalan lebih cepat. Namun saya telah mengamati beberapa hal:

  1. Setelah modifikasi file "py", perilaku program berubah. Hal ini menunjukkan bahwa file "py" telah dikompilasi atau setidaknya melalui proses hashing atau membandingkan stempel waktu untuk mengetahui apakah file tersebut harus dikompilasi ulang atau tidak.
  2. Setelah menghapus semua file ".pyc" ( rm *.pyc) terkadang perilaku program akan berubah. Yang menunjukkan bahwa mereka tidak dikompilasi pada pembaruan ".py".

Pertanyaan:

  • Bagaimana mereka memutuskan kapan akan dikompilasi?
  • Adakah cara untuk memastikan bahwa mereka memiliki pemeriksaan yang lebih ketat selama pengembangan?

15
Waspadalah terhadap menghapus file .pyc dengan rm *.pyc. Ini tidak akan menghapus file .pyc dalam folder bersarang. Gunakan find . -name '*.pyc' -deletesebagai gantinya
Zags

6
Mungkin satu catatan untuk pertanyaan Anda: Sebuah program tidak berjalan lebih cepat ketika dibaca dari file '.pyc' atau '.pyo' daripada ketika dibaca dari file '.py'; satu-satunya hal yang lebih cepat tentang file '.pyc' atau '.pyo' adalah kecepatan pemuatannya. tautan
maggie

@ Maggie apa perbedaan antara waktu pemuatan dan eksekusi?
Daniel Springer

3
@Dani loading adalah waktu yang dibutuhkan untuk membaca dan kemudian mengkompilasi program. Waktu eksekusi adalah saat program benar-benar dijalankan yang terjadi setelah pemuatan. Jika Anda ingin lebih teknis, jenis waktunya adalah waktu buka, waktu kompilasi, waktu tautan, dan waktu eksekusi. Membuat .pyc menghilangkan bagian waktu kompilasi.
Eric Klien

@EricKlien berterima kasih kepada manusia
Daniel Springer

Jawaban:


81

The .pycfile diciptakan (dan mungkin ditimpa) hanya ketika file python diimpor oleh beberapa script lainnya. Jika impor dipanggil, Python memeriksa untuk melihat apakah .pycstempel waktu internal file tidak lebih lama dari .pyfile yang sesuai . Jika ya, itu memuat .pyc; jika tidak atau jika .pycbelum ada, Python mengkompilasi .pyfile menjadi a .pycdan memuatnya.

Apa yang Anda maksud dengan "pemeriksaan yang lebih ketat"?


3
Saya bisa memperbaiki masalah dengan rm *.pyc. Saya tahu bahwa jika saya memaksa semua file untuk dibuat ulang, maka beberapa masalah telah diperbaiki, yang menunjukkan bahwa file tidak dikompilasi ulang sendiri. Saya kira jika mereka menggunakan stempel waktu maka tidak ada cara untuk membuat perilaku ini lebih ketat, tetapi masalahnya masih berlanjut.
Aaron Schif

14
Ini tidak sepenuhnya benar. Stempel waktu tidak perlu cocok (dan biasanya tidak). The .pyc's timestamp harus lebih tua dari yang sesuai .py' s timestamp untuk memicu kompilasi ulang sebuah.
Tim Pietzcker

4
@ Aaron, Apakah Anda mungkin mengubah file .py, dan dalam proses membuatnya lebih lama (misalnya dengan menyalinnya dari direktori lain, menggunakan operasi yang mempertahankan 'waktu modifikasi')?
greggo

1
@greggo, saya menggunakan git dan memperbarui dari repositori, jadi ya dengan cara saya. Itu bisa melakukannya. Terima kasih.
Aaron Schif

1
Senang mendengarnya. Bagaimana kalau mengoreksi jawaban Anda?
Piotr Dobrogost

30

File .pyc dibuat setiap kali elemen kode yang sesuai diimpor, dan diperbarui jika file kode terkait telah diperbarui. Jika file .pyc dihapus, mereka akan dibuat ulang secara otomatis. Namun, mereka tidak secara otomatis dihapus ketika file kode terkait dihapus.

Ini dapat menyebabkan beberapa bug yang sangat menyenangkan selama refactors tingkat file.

Pertama-tama, Anda dapat mendorong kode yang hanya berfungsi pada mesin Anda dan tidak pada mesin orang lain. Jika Anda memiliki referensi yang menggantung ke file yang Anda hapus, ini akan tetap berfungsi secara lokal jika Anda tidak menghapus file .pyc yang relevan secara manual karena file .pyc dapat digunakan dalam impor. Ini ditambah dengan fakta bahwa sistem kontrol versi yang dikonfigurasi dengan benar hanya akan mendorong file .py ke repositori pusat, bukan file .pyc, yang berarti bahwa kode Anda dapat lulus "uji impor" (melakukan impor semuanya dengan baik) dengan baik dan tidak bekerja di komputer orang lain.

Kedua, Anda dapat memiliki beberapa bug yang cukup parah jika Anda mengubah paket menjadi modul. Saat Anda mengonversi paket (folder dengan __init__.pyfile) menjadi modul (file .py), file .pyc yang pernah mewakili paket itu tetap ada. Secara khusus, __init__.pycsisa - sisa. Jadi, jika Anda memiliki paket foo dengan beberapa kode yang tidak masalah, kemudian hapus paket itu dan buat file foo.py dengan beberapa fungsi def bar(): passdan jalankan:

from foo import bar

Anda mendapatkan:

ImportError: cannot import name bar

karena python masih menggunakan file .pyc lama dari paket foo, tidak ada yang mendefinisikan bilah. Hal ini dapat menjadi masalah terutama pada server web, di mana kode yang berfungsi total dapat rusak karena file .pyc.

Sebagai hasil dari kedua alasan ini (dan mungkin yang lainnya), kode penerapan dan kode pengujian Anda harus menghapus file .pyc, seperti dengan baris bash berikut:

find . -name '*.pyc' -delete

Selain itu, pada python 2.6, Anda dapat menjalankan python dengan -Bflag untuk tidak menggunakan file .pyc. Lihat Bagaimana cara menghindari file .pyc? untuk lebih jelasnya.

Lihat juga: Bagaimana cara menghapus semua file .pyc dari sebuah proyek?


"Saat Anda mengonversi modul (folder dengan __init__.pyfile) ...". Itu akan menjadi sebuah paket, bukan modul.
Robert David Grant

2
Secara khusus, __init__.pycsisa - sisa. - Bagaimana bisa? Karena paket adalah direktori, menghapus paket berarti menghapus direktori sehingga tidak ada file yang tersisa…
Piotr Dobrogost

3
@PiotrDobrogost Kontrol sumber yang dikelola dengan benar melibatkan tidak memeriksa file pyc Anda ke dalam sumber. Jadi, meskipun Anda dapat menghapus folder, termasuk file pyc, di salinan lokal Anda, folder itu tidak akan dihapus untuk orang lain yang melakukan git pull. Ini dapat merusak server Anda jika penerapan Anda melibatkan git pull juga.
Zags

Ada banyak alasan untuk tidak mempercayai lingkungan dev Anda sebagai perwakilan tempat kode Anda akan diterapkan. .pycMasalah ini adalah salah satu alasannya, juga: ketergantungan tersembunyi pada OS dan tingkat tambalan utilitas, .sofile , file konfigurasi, libs Python lainnya (jika Anda tidak menjalankan virtual env), mengaburkan env vars ... daftarnya terus berlanjut. Untuk teliti dan menemukan semua masalah seperti itu, Anda perlu membuat salinan bersih kode Anda di repo git atau menerbitkan sebagai paket ke server gaya PyPi, dan melakukan klon penuh atau penyiapan pada VM baru. Beberapa dari masalah potensial tersebut membuat masalah ini menjadi .pycpucat jika dibandingkan.
Chris Johnson
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.