¿Python es interpretado, compilado o ambos?


190

Desde mi entendimiento:

Un lenguaje interpretado es un lenguaje de alto nivel ejecutado y ejecutado por un intérprete (un programa que convierte el lenguaje de alto nivel en código de máquina y luego lo ejecuta) sobre la marcha; procesa el programa poco a poco.

Un lenguaje compilado es un lenguaje de alto nivel cuyo código primero se convierte en código máquina por un compilador (un programa que convierte el lenguaje de alto nivel en código máquina) y luego lo ejecuta un ejecutor (otro programa para ejecutar el código).

Corrígeme si mis definiciones son incorrectas.

Ahora volviendo a Python, estoy un poco confundido acerca de esto. En todas partes se aprende que Python es un lenguaje interpretado, pero se interpreta en algún código intermedio (como byte-code o IL) y no en el código de la máquina. Entonces, ¿qué programa ejecuta el código IM? Por favor, ayúdame a entender cómo se maneja y ejecuta un script Python.



2
Python crea archivos .pyc (denominado byecode) cada vez que se importa una biblioteca. AFAIK el bytecode solo puede acelerar los tiempos de carga, no los tiempos de ejecución.
Jesvin Jose

2
@aitchnyu: el almacenamiento en caché del código de bytes en archivos .pyc solo acelera la carga, pero solo porque el código de Python se compila en código de bytes antes de la ejecución de todos modos. Aunque no creo que se haya intentado específicamente con Python, otras implementaciones de lenguaje muestran que bytecode es de hecho más fácil de interpretar de manera eficiente que un AST simple o, peor aún, un código fuente no analizado. Las versiones anteriores de Ruby interpretadas desde AST, por ejemplo, y AFAIK superó bastante a las versiones más nuevas que compilan en código de bytes.

¿No quieres parecer grosero, pero no es eso lo que quise decir (pero no tan informado como tú)?
Jesvin Jose

1
@aitchnyu: No sé a qué te referías. Solo sé que su comentario no fue incorrecto, pero proporcionó una buena oportunidad para obtener información de fondo por la que solo acelera el tiempo de carga, así que decidí agregar esa información. Sin ofender ni

Respuestas:


233

En primer lugar, interpretado / compilado no es una propiedad del lenguaje sino una propiedad de la implementación. Para la mayoría de los idiomas, la mayoría de las implementaciones, si no todas, caen en una categoría, por lo que uno podría guardar algunas palabras diciendo que el idioma también se interpreta / compila, pero sigue siendo una distinción importante, tanto porque ayuda a la comprensión como porque hay bastantes idiomas. con implementaciones utilizables de ambos tipos (principalmente en el ámbito de los lenguajes funcionales, ver Haskell y ML). Además, hay intérpretes y proyectos de C que intentan compilar un subconjunto de Python en código C o C ++ (y posteriormente en código máquina).

En segundo lugar, la compilación no se limita a la compilación anticipada del código de máquina nativo. Un compilador es, en general, un programa que convierte un programa en un lenguaje de programación en un programa en otro lenguaje de programación (podría decirse que incluso puede tener un compilador con el mismo lenguaje de entrada y salida si se aplican transformaciones significativas). Y los compiladores JIT compilan en código máquina nativa en tiempo de ejecución , lo que puede proporcionar una velocidad muy cercana o incluso mejor que la compilación anticipada (según el punto de referencia y la calidad de las implementaciones comparadas).

Pero para dejar de ser quisquilloso y responder la pregunta que quería hacer: Prácticamente (léase: usando una implementación algo popular y madura), se compila Python . No se compiló en el código de máquina antes de tiempo (es decir, "compilado" por la definición restringida y errónea, pero desgraciadamente común), "solo" compilado en bytecode , pero sigue siendo compilación con al menos algunos de los beneficios. Por ejemplo, la declaración a = b.c()se compila en una secuencia de bytes que, cuando se "desmonta", se parece un poco load 0 (b); load_str 'c'; get_attr; call_function 0; store 1 (a). Esta es una simplificación, en realidad es menos legible y un poco más de bajo nivel: puede experimentar con el dismódulo de biblioteca estándar y ver cómo es el verdadero negocio.

Ese bytecode se interpreta (tenga en cuenta que hay una diferencia, tanto en teoría como en rendimiento práctico, entre interpretar directamente y compilar primero en alguna representación intermedia e interpretar eso), como con la implementación de referencia (CPython), o interpretar y compilar a código de máquina optimizado en tiempo de ejecución, como con PyPy .


2
Bien, esto significa que un script de Python se compila primero en bytecode y luego es implementado por un intérprete como CPython, Jython o IronPython, etc.
Pankaj Upadhyay

19
No, se compila en bytecode y luego el bytecode lo ejecuta la VM correspondiente. CPython es tanto el compilador como la VM, pero Jython e IronPython son solo el compilador.
Ignacio Vazquez-Abrams

1
@Igacio: No tengo mucha experiencia con IronPython / Jython, pero ¿al menos Jython no proporciona una capa similar a la de un intérprete? No creo que sea factible intentar convertir Python en el código de bytes JVM de tipo estático. Aún así, un buen punto sobre el compilador y el intérprete son parte del mismo paquete.

2
+1 "... una propiedad de la implementación". Yo mismo habría dicho "permite un shell interactivo"
Jesvin Jose

2
@delnan: Bueno, Jython actúa como una especie de intermediario entre el lenguaje Python y la máquina virtual Java, pero se compila en el código de bytes de Java.
Ignacio Vazquez-Abrams

34

La CPU solo puede entender el código de la máquina. Para los programas interpretados, el objetivo final de un intérprete es "interpretar" el código del programa en código máquina. Sin embargo, por lo general, un lenguaje interpretado moderno no interpreta el código humano directamente porque es demasiado ineficiente.

El intérprete de Python primero lee el código humano y lo optimiza a un código intermedio antes de interpretarlo en código máquina. Es por eso que siempre necesita otro programa para ejecutar un script de Python, a diferencia de C ++, donde puede ejecutar el ejecutable compilado de su código directamente. Por ejemplo, c:\Python27\python.exeo /usr/bin/python.


11
Me gusta el punto sobre "necesitar otro programa para ejecutarlo". Eso ayudó a aclarar algunos de mis pensamientos.
Matt

¿Entonces python.exe primero optimiza el código y luego lo interpreta?
Koray Tugay

@KorayTugay, cuando python.exe recibe un código fuente de texto legible por humanos, primero produce un código de bytes optimizado, luego lo interpreta (como usted dice); sin embargo, cuando ya hay un archivo de código de bytes (precompilado), no tiene que hacer el primer paso, lo que ahorra algo de tiempo.
GordonBGood

31

La respuesta depende de qué implementación de python se esté utilizando. Si está utilizando, digamos CPython (La implementación estándar de python) o Jython (Dirigido para la integración con el lenguaje de programación java), primero se traduce a bytecode , y dependiendo de la implementación de python que esté utilizando, este bycode se dirige al correspondiente Máquina virtual para la interpretación . PVM (Python Virtual Machine) para CPython y JVM (Java Virtual Machine) para Jython.

Pero digamos que está utilizando PyPy, que es otra implementación estándar de CPython. Usaría un compilador Just-In-Time .


Durante la traducción a bytecode necesita un compilador ¿cuál es ese?
RICKY

Pypy es una implementación de Python , no una implementación de "CPython". De hecho, Pypy es una alternativa a CPython ( pypy.org/features.html ).
Giorgio

13

Según el sitio web oficial de Python, es un lenguaje interpretado.

https://www.python.org/doc/essays/blurb/

Python es un lenguaje de programación interpretado, orientado a objetos y de alto nivel ...

...

Como no hay paso de compilación ...

...

El intérprete de Python y la extensa biblioteca estándar están disponibles ...

...

En cambio, cuando el intérprete descubre un error, genera una excepción. Cuando el programa no detecta la excepción, el intérprete imprime un seguimiento de la pila.


7

Sí, es un lenguaje compilado e interpretado. Entonces, ¿por qué generalmente lo llamamos lenguaje interpretado?

¿Ves cómo se compila e interpreta?

En primer lugar, quiero decir que le gustará más mi respuesta si es del mundo Java.

En Java, el código fuente primero se convierte al código de bytes a través del compilador javac y luego se dirige a la JVM (responsable de generar el código nativo para fines de ejecución). Ahora quiero mostrarle que llamamos a Java como lenguaje compilado porque podemos ver que realmente compila el código fuente y le da el archivo .class (nada más que bytecode) a través de:

javac Hello.java -------> produce el archivo Hello.class

java Hola --------> Dirigiendo bytecode a JVM para fines de ejecución

Lo mismo sucede con Python, es decir, primero el código fuente se convierte al código de bytes a través del compilador y luego se dirige al PVM (responsable de generar el código nativo para fines de ejecución). Ahora quiero mostrarle que generalmente llamamos a Python como un lenguaje interpretado porque la compilación ocurre detrás de escena y cuando ejecutamos el código de Python a través de:

python Hello.py -------> extrae directamente el código y podemos ver que la salida proporcionó que el código es sintácticamente correcto

@ python Hello.py parece que se ejecuta directamente, pero realmente genera primero el código de bytes interpretado por el intérprete para producir el código nativo para el propósito de ejecución.

CPython : asume la responsabilidad tanto de la compilación como de la interpretación.

Mire las líneas a continuación si necesita más detalles :

Como mencioné que CPython compila el código fuente, pero la compilación real ocurre con la ayuda de cython, luego la interpretación ocurre con la ayuda de CPython

Ahora hablemos un poco sobre el papel del compilador Just-In-Time en Java y Python

En JVM existe el intérprete Java que interpreta el bytecode línea por línea para obtener el código máquina nativo para fines de ejecución, pero cuando el intérprete ejecuta el bytecode Java, la ejecución siempre será más lenta. ¿Entonces, cuál es la solución? la solución es el compilador Just-In-Time que produce el código nativo que se puede ejecutar mucho más rápido de lo que se podría interpretar. Algunos proveedores de JVM usan Java Interpreter y otros usan el compilador Just-In-Time . Referencia: haga clic aquí

En python para moverse por el intérprete para lograr la ejecución rápida, use otra implementación de python ( PyPy ) en lugar de CPython . Haga clic aquí para otra implementación de Python, incluyendo PyPy .


6

If (You know Java) {El

código Python se convierte en bytecode como lo hace java.
Ese bytecode se ejecuta nuevamente cada vez que intentas acceder a él.

} else {El

código de Python se traduce inicialmente en algo llamado bytecode
que está bastante cerca del lenguaje de máquina pero no del código de máquina real,
por lo que cada vez que accedemos o lo ejecutamos ese bytecode se ejecuta nuevamente

}


2

Casi, podemos decir que Python es lenguaje interpretado. Pero estamos usando una parte del proceso de compilación de una sola vez en Python para convertir el código fuente completo en código de bytes como el lenguaje java.


1

Para los novatos

Python compila automáticamente su script en código compilado, llamado código de bytes, antes de ejecutarlo.

Ejecutar un script no se considera una importación y no se creará .pyc.

Por ejemplo, si tiene un archivo de script abc.py que importa otro módulo xyz.py, cuando ejecute abc.py, se creará xyz.pyc ya que xyz se importa, pero no se creará ningún archivo abc.pyc desde abc. Py no se está importando.


1

Es una gran confusión para las personas que comenzaron a trabajar en Python y las respuestas aquí son un poco difíciles de comprender, así que lo haré más fácil.

Cuando le indicamos a Python que ejecute nuestro script, hay algunos pasos que Python lleva a cabo antes de que nuestro código comience a funcionar:

  • Se compila en bytecode.
  • Luego se enruta a la máquina virtual.

Cuando ejecutamos un código fuente, Python lo compila en un código de bytes. La compilación es un paso de traducción, y el código de bytes es una representación de código fuente independiente de la plataforma de bajo nivel. Tenga en cuenta que el código de bytes de Python no es un código de máquina binario (por ejemplo, instrucciones para un chip Intel).

En realidad, Python traduce cada declaración del código fuente en instrucciones de código de bytes descomponiéndolas en pasos individuales. La traducción del código de bytes se realiza para acelerar la ejecución. El código de bytes se puede ejecutar mucho más rápido que las declaraciones del código fuente original. Tiene la extensión.pyc y se escribirá si puede escribir en nuestra máquina.

Entonces, la próxima vez que ejecutemos el mismo programa, Python cargará el archivo .pyc y omitirá el paso de compilación a menos que se haya cambiado. Python comprueba automáticamente las marcas de tiempo de los archivos de código fuente y de bytes para saber cuándo debe volver a compilarse. Si volvemos a guardar el código fuente, el código de bytes se volverá a crear automáticamente la próxima vez que se ejecute el programa.

Si Python no puede escribir los archivos de código de bytes en nuestra máquina, nuestro programa aún funciona. El código de bytes se genera en la memoria y simplemente se descarta al salir del programa. Pero debido a que los archivos .pyc aceleran el tiempo de inicio, es posible que deseemos asegurarnos de que se haya escrito para programas más grandes.

Resumamos lo que sucede detrás de escena. Cuando un Python ejecuta un programa, Python lee el .py en la memoria, lo analiza para obtener un código de bytes y luego se ejecuta. Para cada módulo importado por el programa, Python primero verifica si hay una versión de código de bytes precompilada, en un .pyo o .pyc, que tiene una marca de tiempo que corresponde a su archivo .py. Python usa la versión de bytecode si la hay. De lo contrario, analiza el archivo .py del módulo, lo guarda en un archivo .pyc y utiliza el código de bytes que acaba de crear.

Los archivos de código de bytes también son una forma de enviar códigos Python. Python seguirá ejecutando un programa si todo lo que puede encontrar son archivos .pyc, incluso si los archivos fuente .py originales no están allí.

Máquina virtual Python (PVM)

Una vez que nuestro programa ha sido compilado en código de bytes, se envía para su ejecución a Python Virtual Machine (PVM). El PVM no es un programa separado. No es necesario que se instale solo. En realidad, el PVM es solo un gran bucle que itera a través de nuestra instrucción de código de bytes, uno por uno, para llevar a cabo sus operaciones. El PVM es el motor de tiempo de ejecución de Python. Siempre está presente como parte del sistema Python. Es el componente que realmente ejecuta nuestros scripts. Técnicamente es solo el último paso de lo que se llama el intérprete de Python.


0

El código de Python que escribe se compila en el código de bytes de Python, que crea un archivo con extensión .pyc. Si compila, nuevamente la pregunta es, ¿por qué no compila el lenguaje?

Tenga en cuenta que esto no es una compilación en el sentido tradicional de la palabra. Por lo general, diríamos que la compilación toma un lenguaje de alto nivel y lo convierte en código de máquina. Pero es una especie de compilación. Compilado en código intermedio, no en código de máquina (Espero que lo tenga ahora).

Regresando al proceso de ejecución, su código de bytes, presente en el archivo pyc, creado en el paso de compilación, es ejecutado por máquinas virtuales apropiadas, en nuestro caso, la VM CPython. La marca de tiempo (llamada como número mágico) se usa para validar si. el archivo py se cambia o no, dependiendo de que se cree el nuevo archivo pyc. Si pyc es de código actual, simplemente omite el paso de compilación.


0

Python (el intérprete) se compila .

Prueba: ni siquiera compilará su código si contiene un error de sintaxis .

Ejemplo 1:

print("This should print") 
a = 9/0 

Salida:

This should print
Traceback (most recent call last):
  File "p.py", line 2, in <module>
    a = 9/0
ZeroDivisionError: integer division or modulo by zero

El código se compila correctamente. Se ejecuta la primera línea ( print) lanzamientos de segunda línea ZeroDivisionError(error de tiempo de ejecución).

Ejemplo 2

print("This should not print")
/0         

Salida:

  File "p.py", line 2
    /0
    ^
SyntaxError: invalid syntax

Conclusión : si su archivo de código SyntaxErrorno contiene nada, se ejecutará ya que la compilación falla.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.