¿Cómo evitar los archivos .pyc?

268

¿Puedo ejecutar el intérprete de Python sin generar los archivos .pyc compilados?

Avner
fuente

Respuestas:

288

De "Qué hay de nuevo en Python 2.6 - Cambios de intérprete" :

Ahora se puede evitar que Python escriba archivos .pyc o .pyo proporcionando el modificador -B al intérprete de Python o configurando la variable de entorno PYTHONDONTWRITEBYTECODE antes de ejecutar el intérprete. Esta configuración está disponible para los programas de Python como la sys.dont_write_bytecodevariable, y el código de Python puede cambiar el valor para modificar el comportamiento del intérprete.

Actualización 2010-11-27: Python 3.2 aborda el problema de desordenar las carpetas de origen con .pycarchivos mediante la introducción de una __pycache__subcarpeta especial , consulte Novedades en Python 3.2 - Directorios del repositorio PYC .

Constantin
fuente
1
Al menos en OS X 10.8 con Python 2.7, la variable de entorno no tiene efecto.
sorin
55
Si está incrustando el intérprete (en un programa C ++), use "Py_DontWriteBytecodeFlag = 1;" en tu código fuente. Ese es un int global declarado en pydebug.h.
JimB
1
La variable de entorno funciona bien para mí en 2.7, no sé qué problemas están teniendo otros. ¡Gracias!
Thomas
8
También funcionó para mí en OSX (10.8 y 10.10); @sorin, ¿exportó la variable correctamente? export PYTHONDONTWRITEBYTECODE=1
nevelis
1
¿Sabes cómo hacer lo mismo con pytest?
110
import sys

sys.dont_write_bytecode = True
te wilson
fuente
25
Acabo de probar esto y funciona para módulos importados. Específicamente, una vez que esta variable se establece, cualquier cosa importada más tarde no generará archivos pyc. Esto es encantador Gracias.
En lugar de agregar esto en el Módulo principal, intente agregar esto en el Script referenciado. Esto funciona bien. Gracias a @te wilson
Sathy
44
Agregue esto a su site-packages/usercustomize.pypara hacer que esto se aplique a todos sus scripts. Para mí, este directorio fue $HOME/.local/lib/python2.6/site-pacakges/usercustomize.py. Cf. docs.python.org/2/tutorial/…
RobM
3
Mis paquetes de sitio estaban ubicados en: /usr/local/lib/python2.7/site-packages y tuve que crear usercustomize.py
anon58192932
3
O en una línea:import sys; sys.dont_write_bytecode = True
ET-CS
23

De hecho, hay una manera de hacerlo en Python 2.3+, pero es un poco esotérico. No sé si te das cuenta de esto, pero puedes hacer lo siguiente:

$ 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'

De acuerdo con la biblioteca zipimport :

Cualquier archivo puede estar presente en el archivo ZIP, pero solo los archivos .py y .py [co] están disponibles para importar. La importación ZIP de módulos dinámicos (.pyd, .so) no está permitida. Tenga en cuenta que si un archivo contiene solo archivos .py, Python no intentará modificar el archivo agregando el archivo .pyc o .pyo correspondiente, lo que significa que si un archivo ZIP no contiene archivos .pyc, la importación puede ser bastante lenta.

Por lo tanto, todo lo que tiene que hacer es comprimir los archivos, agregar el archivo zip a su sys.path y luego importarlos.

Si está compilando esto para UNIX, también puede considerar empaquetar su script usando esta receta: unix zip ejecutable , pero tenga en cuenta que es posible que tenga que modificar esto si planea usar stdin o leer cualquier cosa de sys.args (PUEDE ser hecho sin demasiados problemas).

En mi experiencia, el rendimiento no sufre demasiado debido a esto, pero debe pensarlo dos veces antes de importar módulos muy grandes de esta manera.

Jason Baker
fuente
11

En 2.5, no hay forma de suprimirlo, aparte de medidas como no dar a los usuarios acceso de escritura al directorio.

Sin embargo, en python 2.6 y 3.0, puede haber una configuración en el módulo sys llamada "dont_write_bytecode" que se puede configurar para suprimir esto. Esto también se puede configurar pasando la opción "-B" o configurando la variable de entorno "PYTHONDONTWRITEBYTECODE"

Brian
fuente
7

Puede configurar sys.dont_write_bytecode = Truesu fuente, pero eso tendría que estar en el primer archivo de Python cargado. Si ejecuta, python somefile.pyentonces no obtendrá somefile.pyc.

Cuando instale una utilidad usando setup.pyy entry_points=habrá establecido sys.dont_write_bytecodeen el script de inicio. Por lo tanto, no puede confiar en el script de inicio "predeterminado" generado por setuptools.

Si inicia Python con el archivo python como argumento, puede especificar -B:

python -B somefile.py

somefile.pycno se generaría de todos modos, pero tampoco se .pycimportarían archivos para otros archivos.

Si tiene alguna utilidad myutily no puede cambiarla, no pasará -B al intérprete de Python. Simplemente comience configurando la variable de entorno PYTHONDONTWRITEBYTECODE:

PYTHONDONTWRITEBYTECODE=x myutil
Elwyne
fuente
4

Tengo varios casos de prueba en un conjunto de pruebas y antes de ejecutar el conjunto de pruebas en la Terminal de Mac de esta manera:

python LoginSuite.py

Al ejecutar el comando de esta manera, mi directorio se estaba rellenando con archivos .pyc. Probé el método indicado a continuación y resolvió el problema:

python -B LoginSuite.py

Este método funciona si está importando casos de prueba en el conjunto de pruebas y está ejecutando el conjunto en la línea de comandos.

Ravil Asadov
fuente
4

Comenzando con Python 3.8 , puede usar la variable de entorno PYTHONPYCACHEPREFIXpara definir un directorio de caché para Python.

De los documentos de Python:

Si está configurado, Python escribirá archivos .pyc en un árbol de directorios espejo en esta ruta, en lugar de en los directorios de pycache dentro del árbol de origen. Esto es equivalente a especificar la opción -X pycache_prefix = PATH.

Ejemplo

Si agrega la siguiente línea a su ./profileen Linux:

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

Python no creará los __pycache__directorios molestos en el directorio de su proyecto, sino que los colocará a todos bajo~/.cache/cpython/

Rotareti
fuente
2

Puede hacer que los directorios en los que existen sus módulos sean de solo lectura para el usuario con el que se ejecuta el intérprete de Python.

No creo que haya una opción más elegante. PEP 304 parece haber sido un intento de introducir una opción simple para esto, pero parece haber sido abandonado.

Me imagino que probablemente hay algún otro problema que estás tratando de resolver, para el cual deshabilitar .py [co] parecería ser una solución, pero probablemente sea mejor atacar el problema original.

Logan
fuente
2

Solución para ipython 6.2.1 using python 3.5.2(Probado en Ubuntu 16.04 y Windows 10):

Ipythonno respeta %env PYTHONDONTWRITEBYTECODE =1si está configurado en el ipythonintérprete o durante el inicio en ~/.ipython/profile-default/startup/00-startup.ipy. En lugar de usar lo siguiente en su~.ipython/profile-default/startup/00-startup.py

import sys
sys.dont_write_bytecode=True
alpha_989
fuente
0

Hasta donde sé, Python compilará todos los módulos que "importe". Sin embargo, python NO compilará una secuencia de comandos de Python ejecutada usando: "python script.py" (sin embargo, compilará cualquier módulo que importe la secuencia de comandos).

La verdadera pregunta es por qué no quieres que Python compile los módulos. Probablemente podría automatizar una forma de limpiarlos si se interponen en el camino.

Alex
fuente
He encontrado con frecuencia que hay .pycarchivos de bytecode obsoletos . Por alguna razón, cuando cambio la clase / módulo, el .pycarchivo no se actualiza. Entonces, cuando lo importo después de cambiar el .pyarchivo, seguirá .pyc
usándolo