Bagaimana cara menghindari file .pyc?

268

Dapatkah saya menjalankan interpreter python tanpa menghasilkan file .pyc yang telah dikompilasi?

Avner
sumber

Jawaban:

288

Dari "Apa yang Baru di Python 2.6 - Perubahan Interpreter" :

Python sekarang dapat dicegah dari menulis file .pyc atau .pyo dengan memasok saklar -B ke interpreter Python, atau dengan mengatur variabel lingkungan PYTHONDONTWRITEBYTECODE sebelum menjalankan interpreter. Pengaturan ini tersedia untuk program Python sebagai sys.dont_write_bytecodevariabel, dan kode Python dapat mengubah nilai untuk mengubah perilaku juru bahasa.

Pembaruan 2010-11-27: Python 3.2 membahas masalah mengacaukan folder sumber dengan .pycfile dengan memperkenalkan __pycache__subfolder khusus , lihat Apa yang Baru di Python 3.2 - PYC Repository Directories .

Konstantin
sumber
1
Setidaknya pada OS X 10.8 menjalankan Python 2.7 variabel lingkungan tidak berpengaruh.
Sorin
5
Jika Anda menyematkan interpreter (dalam program C ++), gunakan "Py_DontWriteBytecodeFlag = 1;" dalam kode sumber Anda. Itulah int global yang dideklarasikan di pydebug.h.
JimB
1
Variabel lingkungan berfungsi dengan baik bagi saya di 2.7, tidak tahu masalah apa yang dialami orang lain. Terima kasih!
Thomas
8
Bekerja untuk saya juga di OSX (10.8 & 10.10); @ Atau apakah Anda mengekspor variabel dengan benar? export PYTHONDONTWRITEBYTECODE=1
nevelis
1
Apakah Anda tahu cara melakukan hal yang sama dengan pytest?
110
import sys

sys.dont_write_bytecode = True
te wilson
sumber
25
Saya baru saja mencoba ini dan berfungsi untuk modul yang diimpor. Secara khusus, setelah variabel ini disetel, apa pun yang diimpor nanti tidak akan menghasilkan file pyc. Ini menyenangkan. Terima kasih.
Alih-alih menambahkan ini di Modul Induk, coba tambahkan ini dalam Skrip yang direferensikan. Ini bekerja dengan baik. Terima kasih kepada @te wilson
Sathy
4
Tambahkan ini ke Anda site-packages/usercustomize.pyuntuk menjadikan ini berlaku untuk semua skrip Anda. Bagi saya, direktori ini dulu $HOME/.local/lib/python2.6/site-pacakges/usercustomize.py. Lih docs.python.org/2/tutorial/…
RobM
3
Paket-situs saya terletak di: /usr/local/lib/python2.7/site-packages dan saya harus membuat usercustomize.py
anon58192932
3
Atau dalam satu baris:import sys; sys.dont_write_bytecode = True
ET-CS
23

Sebenarnya ada cara untuk melakukannya dengan Python 2.3+, tapi agak esoterik. Saya tidak tahu apakah Anda menyadarinya, tetapi Anda dapat melakukan hal berikut:

$ unzip -l /tmp/example.zip
 Archive:  /tmp/example.zip
   Length     Date   Time    Name
 --------    ----   ----    ----
     8467  11-26-02 22:30   jwzthreading.py
 --------                   -------
     8467                   1 file
$ ./python
Python 2.3 (#1, Aug 1 2003, 19:54:32) 
>>> import sys
>>> sys.path.insert(0, '/tmp/example.zip')  # Add .zip file to front of path
>>> import jwzthreading
>>> jwzthreading.__file__
'/tmp/example.zip/jwzthreading.py'

Menurut perpustakaan zipimport :

File apa pun mungkin ada dalam arsip ZIP, tetapi hanya file .py dan .py [co] yang tersedia untuk impor. Impor ZIP untuk modul dinamis (.pyd, .so) tidak diizinkan. Perhatikan bahwa jika arsip hanya berisi file .py, Python tidak akan berusaha untuk memodifikasi arsip dengan menambahkan file .pyc atau .pyo yang sesuai, artinya jika arsip ZIP tidak mengandung file .pyc, mengimpor mungkin agak lambat.

Jadi, yang harus Anda lakukan adalah meng-zip file, menambahkan zipfile ke sys.path Anda dan kemudian mengimpornya.

Jika Anda membuat ini untuk UNIX, Anda mungkin juga mempertimbangkan untuk mengemas skrip Anda menggunakan resep ini: unix zip executable , tetapi perhatikan bahwa Anda mungkin harus mengubah ini jika Anda berencana menggunakan stdin atau membaca apa pun dari sys.args (itu BISA dilakukan tanpa terlalu banyak kesulitan).

Dalam pengalaman saya kinerja tidak terlalu menderita karena ini, tetapi Anda harus berpikir dua kali sebelum mengimpor modul yang sangat besar dengan cara ini.

Jason Baker
sumber
11

Dalam 2.5, tidak ada cara untuk menekannya, selain langkah-langkah seperti tidak memberikan pengguna akses tulis ke direktori.

Namun dalam python 2.6 dan 3.0, mungkin ada pengaturan dalam modul sys yang disebut "dont_write_bytecode" yang dapat diatur untuk menekan ini. Ini juga dapat diatur dengan melewatkan opsi "-B", atau mengatur variabel lingkungan "PYTHONDONTWRITEBYTECODE"

Brian
sumber
7

Anda dapat mengatur sys.dont_write_bytecode = Truedi sumber Anda, tetapi itu harus berada di file python pertama yang dimuat. Jika Anda mengeksekusi python somefile.pymaka Anda tidak akan mendapatkannya somefile.pyc.

Ketika Anda menginstal utilitas menggunakan setup.pydan entry_points=Anda akan mengatur sys.dont_write_bytecodeskrip startup. Jadi, Anda tidak dapat mengandalkan skrip startup "default" yang dihasilkan oleh setuptools.

Jika Anda memulai Python dengan file python sebagai argumen sendiri, Anda dapat menentukan -B:

python -B somefile.py

somefile.pyctoh tidak akan dihasilkan, tetapi tidak ada .pycfile untuk file lain yang diimpor juga.

Jika Anda memiliki beberapa utilitas myutildan Anda tidak dapat mengubahnya, itu tidak akan meneruskan -B ke penerjemah python. Mulai saja dengan mengatur variabel lingkungan PYTHONDONTWRITEBYTECODE:

PYTHONDONTWRITEBYTECODE=x myutil
Elwyne
sumber
4

Saya memiliki beberapa test case di test suite dan sebelum saya menjalankan test suite di Terminal Mac seperti ini:

python LoginSuite.py

Menjalankan perintah dengan cara ini direktori saya sedang diisi dengan file .pyc. Saya mencoba metode yang dinyatakan di bawah ini dan itu memecahkan masalah:

python -B LoginSuite.py

Metode ini berfungsi jika Anda mengimpor test case ke dalam test suite dan menjalankan suite di baris perintah.

Ravil Asadov
sumber
4

Dimulai dengan Python 3.8 Anda dapat menggunakan variabel lingkungan PYTHONPYCACHEPREFIXuntuk menentukan direktori cache untuk Python.

Dari dokumen Python:

Jika ini disetel, Python akan menulis file .pyc di pohon direktori mirror di jalur ini, alih-alih dalam direktori pycache di dalam pohon sumber. Ini sama dengan menentukan opsi -X pycache_prefix = PATH.

Contoh

Jika Anda menambahkan baris berikut ke ./profileLinux Anda:

export PYTHONPYCACHEPREFIX="$HOME/.cache/cpython/"

Python tidak akan membuat __pycache__direktori yang menjengkelkan di direktori proyek Anda, sebaliknya itu akan menempatkan semuanya~/.cache/cpython/

Rotareti
sumber
2

Anda bisa membuat direktori di mana modul Anda ada di read-only untuk pengguna yang menjalankan interpreter Python.

Saya tidak berpikir ada opsi yang lebih elegan. PEP 304 tampaknya merupakan upaya untuk memperkenalkan opsi sederhana untuk ini, tetapi tampaknya telah ditinggalkan.

Saya membayangkan mungkin ada beberapa masalah lain yang Anda coba selesaikan, yang menonaktifkan .py [co] tampaknya merupakan solusi, tetapi mungkin akan lebih baik untuk menyerang apa pun masalah asli ini.

Logan
sumber
2

Solusi untuk ipython 6.2.1 using python 3.5.2(Diuji pada Ubuntu 16.04 dan Windows 10):

Ipythontidak menghormati %env PYTHONDONTWRITEBYTECODE =1jika diatur dalam ipythoninterpretor atau selama startup di ~/.ipython/profile-default/startup/00-startup.ipy. Alih-alih menggunakan yang berikut di~.ipython/profile-default/startup/00-startup.py

import sys
sys.dont_write_bytecode=True
alpha_989
sumber
0

Sejauh yang saya tahu python akan mengkompilasi semua modul yang Anda "impor". Namun python TIDAK akan mengkompilasi skrip python dijalankan menggunakan: "python script.py" (namun akan mengkompilasi modul yang diimpor skrip).

Pertanyaan sebenarnya adalah mengapa Anda tidak ingin python mengkompilasi modul? Anda mungkin bisa mengotomatiskan cara membersihkan ini jika mereka menghalangi.

Alex
sumber
Saya telah sering menemukan bahwa ada .pycfile bytecode basi . Untuk beberapa alasan, ketika saya mengubah kelas / modul, .pycfile tidak diperbarui. Jadi ketika saya mengimpornya setelah mengubah .pyfile, itu masih akan menggunakan .pycfile, yang mengarah ke kesalahan
alpha_989