¿Por qué compilar código Python?

241

¿Por qué compilarías un script de Python? Puede ejecutarlos directamente desde el archivo .py y funciona bien, ¿hay alguna ventaja de rendimiento o algo así?

También noto que algunos archivos de mi aplicación se compilan en .pyc mientras que otros no, ¿por qué es esto?

ryeguy
fuente
También puede observar que, incluido el inicio más rápido de su aplicación, también gana seguridad, si no puede compartir su código si es un secreto corporativo.
Please_Dont_Bully_Me_SO_Lords
@PSyLoCKe Realmente, realmente no lo haces. El código de bytes de Python es realmente legible, porque el compilador no necesita ofuscarlo para optimizarlo. (No es que lo optimice mucho ...)
wizzwizz4
1
La razón por la que algunos archivos se compilan automáticamente es porque se importan; por ejemplo, si usa import mylib.pyPython se compilará mylib.pypara que las importdeclaraciones futuras se ejecuten un poco más rápido. Si cambia más tarde mylib.py, entonces se obtendrá re-compilado próxima vez que ha sido importada (Python usa la fecha del archivo de ver que esto sucede.)
fyngyrz

Respuestas:

270

Está compilado en bytecode que se puede usar mucho, mucho, mucho más rápido.

La razón por la que algunos archivos no se compilan es porque el script principal, con el que se invoca, python main.pyse vuelve a compilar cada vez que ejecuta el script. Todos los scripts importados serán compilados y almacenados en el disco.

Adición importante de Ben Blank :

Vale la pena señalar que, si bien la ejecución de un script compilado tiene un tiempo de inicio más rápido (ya que no necesita compilarse), no se ejecuta más rápido.

Georg Schölly
fuente
260
Vale la pena señalar que, si bien la ejecución de un script compilado tiene un tiempo de inicio más rápido (ya que no necesita compilarse), no se ejecuta más rápido.
Ben Blank
24
Un error común. Gracias por compartir.
matpie
1
Además de no requerir compilación, el archivo .pyc es casi siempre más pequeño. Especialmente si comentas mucho. Uno de los míos es 28419 como .py, pero solo 17879 como .pyc, por lo que el tiempo de carga también es mejor. Finalmente, puede precompilar scripts de nivel superior de esta manera: python -m compileall myscript.py
fyngyrz
1
¿Hay alguna diferencia en el consumo de memoria? Estoy probando Python en dispositivos integrados basados ​​en CPU de mips con solo 64 MB de RAM, entonces, ¿hay alguna ventaja en el uso de memoria al iniciar una versión compilada de script de Python?
Valentt
1
@valentt: Probablemente no. No sé mucho sobre las partes internas de Python, pero no creo que el análisis de bytecode requiera mucha memoria en Python. No puedo pensar en algo que necesite mucha memoria para recordar algún estado.
Georg Schölly
80

El archivo .pyc es Python que ya se ha compilado en código de bytes. Python ejecuta automáticamente un archivo .pyc si encuentra uno con el mismo nombre que un archivo .py que invocas.

"Una introducción a Python" dice esto sobre los archivos compilados de Python:

Un programa no se ejecuta más rápido cuando se lee desde un archivo '.pyc' o '.pyo' que cuando se lee desde un archivo '.py'; Lo único que es más rápido acerca de los archivos '.pyc' o '.pyo' es la velocidad con la que se cargan.

La ventaja de ejecutar un archivo .pyc es que Python no tiene que incurrir en la sobrecarga de compilarlo antes de ejecutarlo. Dado que Python compilaría a byte-code antes de ejecutar un archivo .py de todos modos, no debería haber ninguna mejora de rendimiento aparte de eso.

¿Cuánta mejora puede obtener al usar archivos compilados .pyc? Eso depende de lo que haga el guión. Para un script muy breve que simplemente imprime "Hello World", la compilación podría constituir un gran porcentaje del tiempo total de inicio y ejecución. Pero el costo de compilar un script en relación con el tiempo de ejecución total disminuye para los scripts de ejecución más larga.

La secuencia de comandos que nombre en la línea de comandos nunca se guarda en un archivo .pyc. Solo los módulos cargados por ese script "principal" se guardan de esa manera.

Bill Karwin
fuente
3
En muchos casos es difícil ver la diferencia, pero tengo un archivo de Python en particular con más de 300,000 líneas. (Es un montón de cálculos matemáticos generados por otra secuencia de comandos para la prueba) Toma 37 segundos compilar, y solo 2 segundos ejecutar.
wojtow
54

Más:

Primero: ofuscación leve y vencible.

Segundo: si la compilación resulta en un archivo significativamente más pequeño, obtendrá tiempos de carga más rápidos. Agradable para la web.

Tercero: Python puede omitir el paso de compilación. Más rápido en carga inicial. Agradable para la CPU y la web.

Cuarto: cuanto más comentes, más pequeño será el archivo .pyco .pyoen comparación con la fuente.py archivo .

Quinto: un usuario final con solo un .pyco.pyo archivo en la mano es mucho menos probable que le presente un error que causó por un cambio no revertido del que se olvidó informarle.

Sexto: si apunta a un sistema incrustado, obtener un archivo de menor tamaño para incrustar puede representar una ventaja significativa, y la arquitectura es estable, por lo que el inconveniente, que se detalla a continuación, no entra en juego.

Compilación de nivel superior

Es útil saber que puede compilar un archivo fuente de Python de nivel superior en un .pycarchivo de esta manera:

python -m py_compile myscript.py

Esto elimina los comentarios. Se deja docstringsintacto. Si también desea deshacerse de él docstrings(es posible que desee pensar seriamente en por qué lo está haciendo), compile de esta manera en su lugar ...

python -OO -m py_compile myscript.py

... y obtendrá un .pyoarchivo en lugar de un .pycarchivo; igualmente distribuible en términos de la funcionalidad esencial del código, pero más pequeño por el tamaño del despojado docstrings(y menos fácilmente entendible para el empleo posterior si tuviera decentedocstrings en primer lugar). Pero vea el inconveniente tres, a continuación.

Tenga en cuenta que python usa la .pyfecha del archivo, si está presente, para decidir si debe ejecutar el .pyarchivo en lugar del archivo .pyco .pyo--- así que edite su archivo .py, y el .pyco .pyoes obsoleto y se pierden los beneficios que obtuvo. Debe volver a compilarlo para recuperar nuevamente los beneficios .pyco .pyobeneficios, como pueden ser.

Inconvenientes:

Primero: hay una "cookie mágica" .pycy .pyoarchivos que indican la arquitectura del sistema en la que se compiló el archivo Python. Si distribuye uno de estos archivos en un entorno de un tipo diferente, se romperá. Si distribuye el .pyco .pyosin el asociado .pypara recompilar o touchreemplaza el .pyco .pyo, el usuario final tampoco podrá solucionarlo.

Segundo: si docstringsse omite con el uso de la -OOopción de línea de comando como se describe anteriormente, nadie podrá obtener esa información, lo que puede hacer que el uso del código sea más difícil (o imposible).

Tercero: la -OOopción de Python también implementa algunas optimizaciones según la -Oopción de línea de comando; Esto puede resultar en cambios en la operación. Las optimizaciones conocidas son:

  • sys.flags.optimize = 1
  • assert las declaraciones se saltan
  • __debug__ = Falso

Cuarto: si intencionalmente hiciste que tu script de Python fuera ejecutable con algo del orden de #!/usr/bin/pythonla primera línea, esto se elimina .pycy los .pyoarchivos y esa funcionalidad se pierde.

Quinto: algo obvio, pero si compila su código, no solo puede verse afectado su uso, sino que el potencial de que otros aprendan de su trabajo se reduce, a menudo severamente.

fyngyrz
fuente
10

Hay un aumento en el rendimiento al ejecutar python compilado. Sin embargo, cuando ejecuta un archivo .py como módulo importado, python lo compilará y almacenará, y siempre que el archivo .py no cambie, siempre usará la versión compilada.

Con cualquier lenguaje interpelado cuando se usa el archivo, el proceso se ve más o menos así:
1. El interpeter procesa el archivo.
2. Se compila el archivo
3. Se ejecuta el código compilado.

obviamente, mediante el uso de código precompilado puede eliminar el paso 2, esto aplica python, PHP y otros.

Aquí hay una publicación de blog interesante que explica las diferencias http://julipedia.blogspot.com/2004/07/compiled-vs-interpreted-languages.html
Y aquí hay una entrada que explica el proceso de compilación de Python http://effbot.org/zone /python-compile.htm

UnkwnTech
fuente
9

Como ya se mencionó, puede obtener un aumento de rendimiento al compilar su código de Python en bytecode. Esto normalmente lo maneja Python, solo para scripts importados.

Otra razón por la que es posible que desee compilar su código de Python, podría ser para proteger su propiedad intelectual de la copia y / o modificación.

Puede leer más sobre esto en la documentación de Python .

Simon B. Jensen
fuente
2
En lo que respecta a proteger su código, la compilación no ayudará mucho. Compilar ofusca, pero cualquiera que lo desee obtendrá su código independientemente.
Josh Smeaton el
1
@josh eso siempre es posible, si uno puede acceder a la memoria o mirar las instrucciones de la CPU, con suficiente tiempo y voluntad, podrán reconstruir su aplicación.
UnkwnTech
55
De acuerdo, sin embargo, como dijo Unkwntech, eso siempre será posible si la persona está suficientemente determinada. Pero estoy convencido de que será suficiente en la mayoría de las situaciones, en las que por lo general solo desea restringir las personas de "fijar" su código ...
Simon B. Jensen
Idiomas que se compilan a bytecode generalmente no son que difícil de revertir-compilación a menos que tome medidas adicionales para ofuscar ellos - simplemente compilar general no será suficiente.
EJoshuaS - Restablece a Monica el
7

Ciertamente, hay una diferencia de rendimiento cuando se ejecuta un script compilado. Si ejecuta .pyscripts normales , la máquina lo compila cada vez que se ejecuta y esto lleva tiempo. En las máquinas modernas, esto apenas se nota, pero a medida que el script crece, puede convertirse en un problema.

matpie
fuente
7

Algo que no se menciona es la compilación de fuente a fuente . Por ejemplo,nuitka traduce el código de Python a C / C ++ y lo compila en código binario que se ejecuta directamente en la CPU, en lugar del código de bytes de Python que se ejecuta en la máquina virtual más lenta.

Esto puede conducir a aceleraciones significativas, o le permitiría trabajar con Python mientras su entorno depende del código C / C ++.

usuario258532
fuente
4

Utilizamos código compilado para distribuir a los usuarios que no tienen acceso al código fuente. Básicamente para evitar que los programadores inexpertos cambien accidentalmente algo o corrijan errores sin avisarnos.

DrBwts
fuente
2

Sí, el rendimiento es la razón principal y, hasta donde yo sé, la única razón.

Si algunos de sus archivos no se compilan, tal vez Python no pueda escribir en el archivo .pyc, tal vez debido a los permisos del directorio o algo así. O tal vez los archivos no compilados simplemente nunca se cargan ... (los scripts / módulos solo se compilan cuando se cargan por primera vez)

David Z
fuente
1

Los principiantes asumen que Python se compila debido a los archivos .pyc. El archivo .pyc es el bytecode compilado, que luego se interpreta. Entonces, si ya ha ejecutado su código de Python y tiene a mano el archivo .pyc, se ejecutará más rápido la segunda vez, ya que no tiene que volver a compilar el código de bytes

compilador: un compilador es una pieza de código que traduce el lenguaje de alto nivel al lenguaje máquina

Intérpretes: los intérpretes también convierten el lenguaje de alto nivel en equivalentes binarios legibles por máquina. Cada vez que un intérprete obtiene un código de lenguaje de alto nivel para ser ejecutado, convierte el código en un código intermedio antes de convertirlo en el código de la máquina. Cada parte del código se interpreta y luego se ejecuta por separado en una secuencia y se encuentra un error en una parte del código que detendrá la interpretación del código sin traducir el siguiente conjunto de códigos.

Fuentes: http://www.toptal.com/python/why-are-there-so-many-pythons http://www.engineersgarage.com/contribution/difference-between-compiler-and-interpreter

Principiante
fuente
99
Su definición de "compilador" es incorrecta. Un compilador nunca ha estado debajo para compilar en código máquina. Un compilador es simplemente un traductor de un idioma a otro. Es por eso que decimos que Python "compila" a bytecode, Coffeescript "compila" a Javascript, y así sucesivamente.
Ricky Stewart