¿Java "Máquina virtual" versus lenguaje de "intérprete" de Python?


207

Parece raro leer una "máquina virtual" de Python mientras que en Java se usa "máquina virtual" todo el tiempo.

Ambos interpretan códigos de bytes; ¿Por qué llamar a uno máquina virtual y al otro intérprete?

Respuestas:


137

Una máquina virtual es un entorno de computación virtual con un conjunto específico de instrucciones atómicas bien definidas que son compatibles independientemente de cualquier lenguaje específico y generalmente se considera como un sandbox en sí mismo. La VM es análoga a un conjunto de instrucciones de una CPU específica y tiende a funcionar en un nivel más fundamental con bloques de construcción muy básicos de tales instrucciones (o códigos de bytes) que son independientes de la siguiente. Una instrucción se ejecuta de manera determinista solo en función del estado actual de la máquina virtual y no depende de la información en otra parte del flujo de instrucciones en ese momento.

Un intérprete, por otro lado, es más sofisticado porque está diseñado para analizar una secuencia de cierta sintaxis que es de un lenguaje específico y de una gramática específica que debe decodificarse en el contexto de los tokens circundantes. No puede ver cada byte o incluso cada línea de forma aislada y saber exactamente qué hacer a continuación. Los tokens en el idioma no pueden tomarse de forma aislada como pueden hacerlo en relación con las instrucciones (códigos de bytes) de una VM.

Un compilador de Java convierte el lenguaje Java en una secuencia de código de bytes no diferente a un compilador de C convierte los programas de lenguaje C en código de ensamblaje. Por otro lado, un intérprete realmente no convierte el programa en ninguna forma intermedia bien definida, solo toma las acciones del programa como una cuestión del proceso de interpretación de la fuente.

Otra prueba de la diferencia entre una VM y un intérprete es si piensas que es independiente del lenguaje. Lo que conocemos como Java VM no es realmente específico de Java. Puede crear un compilador de otros idiomas que genere códigos de bytes que se puedan ejecutar en la JVM. Por otro lado, no creo que realmente pensemos en "compilar" otro lenguaje que no sea Python en Python para que el intérprete de Python lo interprete.

Debido a la sofisticación del proceso de interpretación, este puede ser un proceso relativamente lento ... específicamente analizar e identificar los tokens del lenguaje, etc. y comprender el contexto de la fuente para poder llevar a cabo el proceso de ejecución dentro del intérprete. Para ayudar a acelerar dichos lenguajes interpretados, aquí es donde podemos definir formas intermedias de código fuente pre-analizado y pre-tokenizado que se interprete más fácilmente directamente. Este tipo de forma binaria todavía se interpreta en tiempo de ejecución, solo está comenzando desde una forma mucho menos legible para mejorar el rendimiento. Sin embargo, la lógica que ejecuta esa forma no es una máquina virtual, porque esos códigos aún no se pueden tomar de forma aislada: el contexto de los tokens circundantes aún importa, ahora están en una forma diferente más eficiente en la computadora.


77
Tenía la impresión de que Python generó código de bytes, pyc, o es a lo que se refiere con "ayudar a acelerar dichos lenguajes interpretados, aquí es donde podemos definir formas intermedias de código fuente pre-analizado y pre-tokenizado que es más fácilmente interpretado directamente ".
James McMahon el

32
@InSciTek Jeff: De tu respuesta no está claro si sabes que Python también usa una máquina virtual.
tzot

3
@TZ: la popular implementación de Python es un compilador de Python con una VM posterior. En modo interactivo, es un poco híbrido con un intérprete front-end y un compilador back-end. Sin embargo, esas son opciones de implementación. Traté de describir la diferencia entre el concepto de VM e Intérprete
Tall Jeff

8
On the other hand, I don't think we would really think of "compiling" some other language other than Python into Python for interpretation by the Python interpreter.Es posible escribir un lenguaje que se pueda compilar en el código de bytes de Python, al igual que Scala se compila en el código de bytes de Java. En modo interactivo, el shell interactivo de Python compila su comando escrito en bytecode y ejecuta ese bytecode. Puede escribir su propio shell usando eval y exec, y puede usar la función incorporada compile () para convertir una cadena en bytecode.
Lie Ryan

44
@Lie Ryan sí, pero no es oficialmente compatible como lo es con la JVM. En Python, bytecode es un detalle de implementación no documentado.
Antimonio

159

En esta publicación, "máquina virtual" se refiere a máquinas virtuales de proceso, no a máquinas virtuales de sistema como Qemu o Virtualbox. Una máquina virtual de proceso es simplemente un programa que proporciona un entorno de programación general, un programa que se puede programar.

Java tiene un intérprete y una máquina virtual, y Python tiene una máquina virtual y un intérprete. La razón por la que "máquina virtual" es un término más común en Java y "intérprete" es un término más común en Python tiene mucho que ver con la gran diferencia entre los dos idiomas: escritura estática (Java) frente a escritura dinámica (Python). En este contexto, "tipo" se refiere a tipos de datos primitivos , tipos que sugieren el tamaño de almacenamiento en memoria de los datos. La máquina virtual Java lo tiene fácil. Requiere que el programador especifique el tipo de datos primitivos de cada variable. Esto proporciona información suficiente para que el código de bytes de Java no solo sea interpretado y ejecutado por la máquina virtual Java, sino incluso para ser compilado en las instrucciones de la máquina.. La máquina virtual Python es más compleja en el sentido de que asume la tarea adicional de pausar antes de la ejecución de cada operación para determinar los tipos de datos primitivos para cada variable o estructura de datos involucrada en la operación. Python libera al programador de pensar en términos de tipos de datos primitivos y permite que las operaciones se expresen a un nivel superior. El precio de esta libertad es el rendimiento. "Intérprete" es el término preferido para Python porque tiene que hacer una pausa para inspeccionar los tipos de datos, y también porque la sintaxis comparativamente concisa de los lenguajes de tipo dinámico es una buena opción para las interfaces interactivas. No existe una barrera técnica para construir una interfaz Java interactiva, pero tratar de escribir cualquier tipo de código estático de forma interactiva sería tedioso, por lo que simplemente no se hace de esa manera.

En el mundo de Java, la máquina virtual roba el espectáculo porque ejecuta programas escritos en un lenguaje que en realidad puede compilarse en instrucciones de la máquina, y el resultado es la velocidad y la eficiencia de los recursos. Java bytecode puede ser ejecutado por la máquina virtual Java con un rendimiento cercano al de los programas compilados, en términos relativos. Esto se debe a la presencia de información de tipo de datos primitiva en el código de bytes. La máquina virtual Java coloca a Java en una categoría propia:

lenguaje de tipo estático interpretado portátil

Lo siguiente más cercano es LLVM, pero LLVM opera a un nivel diferente:

lenguaje ensamblador interpretado portátil

El término "bytecode" se usa tanto en Java como en Python, pero no todos los bytecode se crean de la misma manera. bytecode es solo el término genérico para los idiomas intermedios utilizados por los compiladores / intérpretes. Incluso los compiladores de C como gcc usan un lenguaje intermedio (o varios) para hacer el trabajo. El código de bytes de Java contiene información sobre tipos de datos primitivos, mientras que el código de bytes de Python no. A este respecto, la máquina virtual Python (y Bash, Perl, Ruby, etc.) es fundamentalmente más lenta que la máquina virtual Java, o más bien, simplemente tiene más trabajo por hacer. Es útil considerar qué información está contenida en diferentes formatos de bytecode:

  • llvm: registros de la CPU
  • Java: tipos de datos primitivos
  • Python: tipos definidos por el usuario

Para dibujar una analogía del mundo real: LLVM funciona con átomos, la máquina virtual Java funciona con moléculas y la máquina virtual Python funciona con materiales. Como todo debe descomponerse finalmente en partículas subatómicas (operaciones reales de la máquina), la máquina virtual Python tiene la tarea más compleja.

Los intérpretes / compiladores de lenguajes de tipo estático simplemente no tienen el mismo bagaje que los intérpretes / compiladores de lenguajes de tipo dinámico. Los programadores de lenguajes de tipo estático tienen que tomar el relevo, por lo que la recompensa es el rendimiento. Sin embargo, así como todas las funciones no deterministas son secretamente deterministas, también lo son todos los lenguajes dinámicamente tipados secretamente estáticamente. Por lo tanto, las diferencias de rendimiento entre las dos familias de idiomas deberían nivelarse alrededor del tiempo en que Python cambia su nombre a HAL 9000.

Las máquinas virtuales de lenguajes dinámicos como Python implementan una máquina lógica idealizada, y no necesariamente se corresponden muy estrechamente con ningún hardware físico real. La máquina virtual Java, por el contrario, es más similar en funcionalidad a un compilador de C clásico, excepto que en lugar de emitir instrucciones de la máquina, ejecuta rutinas integradas. En Python, un entero es un objeto de Python con un conjunto de atributos y métodos asociados. En Java, un int es un número designado de bits, generalmente 32. No es realmente una comparación justa. Los enteros de Python realmente deberían compararse con la clase de enteros de Java. El tipo de datos primitivo "int" de Java no se puede comparar con nada en el lenguaje Python, porque el lenguaje Python simplemente carece de esta capa de primitivas, y también lo hace el código de bytes de Python.

Debido a que las variables de Java se escriben explícitamente, uno puede esperar razonablemente que algo como el rendimiento de Jython esté en el mismo estadio que cPython . Por otro lado, una máquina virtual Java implementada en Python casi garantiza que sea más lenta que el barro. Y no esperes que a Ruby, Perl, etc., les vaya mejor. No fueron diseñados para hacer eso. Fueron diseñados para "scripting", que es como se llama la programación en un lenguaje dinámico.

Cada operación que se lleva a cabo en una máquina virtual finalmente tiene que llegar al hardware real. Las máquinas virtuales contienen rutinas precompiladas que son lo suficientemente generales como para ejecutar cualquier combinación de operaciones lógicas. Una máquina virtual puede no estar emitiendo nuevas instrucciones de máquina, pero ciertamente está ejecutando sus propias rutinas una y otra vez en secuencias arbitrariamente complejas. La máquina virtual Java, la máquina virtual Python y todas las otras máquinas virtuales de uso general son iguales en el sentido de que pueden ser inducidas a realizar cualquier lógica que pueda imaginar, pero son diferentes en términos de las tareas que realizan. asumir y qué tareas le dejan al programador.

Psyco for Python no es una máquina virtual completa de Python, sino un compilador justo a tiempo que secuestra la máquina virtual Python normal en los puntos que cree que puede compilar algunas líneas de código, principalmente bucles donde cree que el tipo primitivo de algunos La variable permanecerá constante incluso si el valor cambia con cada iteración. En ese caso, puede renunciar a parte de la determinación del tipo incesante de la máquina virtual normal. Sin embargo, debes tener un poco de cuidado, para no sacar el tipo de debajo de los pies de Psyco. Sin embargo, Pysco generalmente sabe que debe recurrir a la máquina virtual normal si no está completamente seguro de que el tipo no cambiará.

La moraleja de la historia es que la información primitiva del tipo de datos es realmente útil para un compilador / máquina virtual.

Finalmente, para ponerlo todo en perspectiva, considere esto: un programa Python ejecutado por un intérprete de Python / máquina virtual implementado en Java que se ejecuta en un intérprete de Java / máquina virtual implementado en LLVM que se ejecuta en una máquina virtual qemu que se ejecuta en un iPhone.

enlace permanente


1
trying to write any statically-typed code interactively would be tedious. Si conoce OCaml y Haskell, verá que eso no es cierto, ya que son lenguajes de tipo estático muy concisos.
Matthias Braun

@MatthiasBraun Estoy de acuerdo en que esos lenguajes funcionales producen código conciso, pero eso no significa necesariamente que sean adecuados para el modo interactivo. Si OCaml y Haskell se escribieran dinámicamente como lisp, supongo que funcionarían mejor para el modo interactivo.
Bombas

58

Probablemente, una de las razones de la diferente terminología es que normalmente se piensa en alimentar al intérprete de Python con un código fuente sin formato legible por humanos y no preocuparse por el código de bytes y todo eso.

En Java, debe compilar explícitamente en bytecode y luego ejecutar solo el bytecode, no el código fuente en la VM.

A pesar de que Python usa una máquina virtual debajo de las cubiertas, desde la perspectiva del usuario, uno puede ignorar este detalle la mayor parte del tiempo.


1
Estoy de acuerdo. Esta diferencia en la terminología realmente se reduce a la experiencia del usuario final (desarrollador, es decir). No tiene nada que ver con las diferencias técnicas reales, ya que la línea técnica es tan increíblemente borrosa que casi no existe.
Cody Brocious

1
+1: Y, lo que es más importante, ¿cuál es el punto? ¿Qué programa no puedes escribir debido a esta distinción? ¿Qué seguimiento de pila te confunde? ¿Qué biblioteca no parece funcionar correctamente?
S.Lott

@ S.Lott Porque siempre es bueno ganar discusiones con colegas. ;)
Qix - MONICA FUE MALTRATADA el

16

El intérprete traduce el código fuente en una representación intermedia eficiente (código) y lo ejecuta de inmediato.

Virtual Machine , ejecuta explícitamente el código precompilado almacenado creado por un compilador que forma parte del sistema de intérprete.

Una característica muy importante de una máquina virtual es que el software que se ejecuta en el interior está limitado a los recursos proporcionados por la máquina virtual. Precisamente, no puede salir de su mundo virtual. Piense en la ejecución segura de código remoto, Applets Java.

En el caso de Python, si mantenemos archivos pyc , como se menciona en el comentario de esta publicación, entonces el mecanismo se parecería más a una VM, y este código de bytes se ejecuta más rápido: aún se interpretaría pero desde una forma mucho más amigable para la computadora . Si miramos esto como un todo, PVM es un último paso de Python Interpreter.

La conclusión es, cuando se refiere a Python Interpreter, significa que lo estamos refiriendo como un todo, y cuando decimos PVM, eso significa que solo estamos hablando de una parte de Python Interpreter, un entorno de tiempo de ejecución. Similar a la de Java, nos referimos a diferentes partes differentyl, JRE, JVM, JDK, etc.

Para más información, entrada de Wikipedia: intérprete y máquina virtual . Otro más aquí . Aquí puede encontrar la Comparación de máquinas virtuales de aplicaciones . Ayuda a comprender la diferencia entre compiladores, intérpretes y máquinas virtuales.


12

El término intérprete es un término heredado que se remonta a lenguajes de script de shell anteriores. A medida que los "lenguajes de secuencias de comandos" se han convertido en lenguajes completos y sus plataformas correspondientes se han vuelto más sofisticadas y protegidas, la distinción entre una máquina virtual y un intérprete (en el sentido de Python) es muy pequeña o inexistente.

El intérprete de Python todavía funciona de la misma manera que un script de shell, en el sentido de que puede ejecutarse sin un paso de compilación separado. Más allá de eso, las diferencias entre el intérprete de Python (o Perl o Ruby) y la máquina virtual de Java son principalmente detalles de implementación. (Se podría argumentar que Java está más protegido que Python, pero ambos proporcionan acceso a la arquitectura subyacente a través de una interfaz C nativa).


1
Hay shells de Java que pueden ejecutar código Java sin pasos de compilación separados (visibles para el usuario).
Lie Ryan

1
dame el nombre: D
Maciej Nowicki

11

Para proporcionar una respuesta profunda a la pregunta " ¿Por qué Java Virtual Machine, pero Python interprete? ", Intentemos volver al campo de la teoría de compilación en cuanto al punto de partida de la discusión.

El proceso típico de compilación del programa incluye los siguientes pasos:

  1. Análisis léxico . Divide el texto del programa en "palabras" significativas llamadas tokens (como parte del proceso se eliminan todos los comentarios, espacios, líneas nuevas, etc., porque no afectan el comportamiento del programa). El resultado es una secuencia ordenada de tokens.
  2. Análisis de sintaxis . Construye el llamado Árbol de sintaxis abstracta (AST) a partir de la secuencia de tokens. AST establece relaciones entre tokens y, como consecuencia, define un orden de evaluación del programa.
  3. Análisis semántico . Verifica la corrección semántica del AST utilizando información sobre tipos y un conjunto de reglas semánticas del lenguaje de programación. (Por ejemplo, a = b + ces una declaración correcta desde el punto de vista de la sintaxis, pero completamente incorrecta desde el punto de vista semántico si ase declaró como un objeto constante)
  4. Generación de código intermedio . Serializa AST en la secuencia ordenada linealmente de operaciones "primitivas" independientes de la máquina. De hecho, el generador de código atraviesa AST y registra el orden de los pasos de evaluación. Como resultado, a partir de la representación en forma de árbol del programa, logramos una representación en forma de lista mucho más simple en la que se conserva el orden de evaluación del programa.
  5. Generación de código de máquina . El programa en forma de código de bytes "primitivo" independiente de la máquina se traduce en código de máquina de arquitectura de procesador particular.

Okay. Ahora definamos los términos.

El intérprete , en el sentido clásico de esa palabra, asume la ejecución basada en la evaluación del programa basada en AST producida directamente del texto del programa . En ese caso, un programa se distribuye en forma de código fuente y el intérprete es alimentado por el texto del programa, con frecuencia de forma dinámica (enunciado por enunciado o línea por línea). Para cada declaración de entrada, el intérprete construye su AST e inmediatamente lo evalúa cambiando el "estado" del programa. Este es un comportamiento típico demostrado por los lenguajes de script. Considere, por ejemplo, Bash, CMD de Windows, etc. Conceptualmente, Python también toma este camino.

Si reemplazamos el paso de ejecución basado en AST en la generación del paso de bytecode binario intermedio independiente de la máquina en el intérprete, dividiremos todo el proceso de ejecución del programa en dos fases separadas: compilación y ejecución. En ese caso, lo que anteriormente era un intérprete se convertirá en un compilador de bytecode, que transformará el programa de la forma del texto a alguna forma binaria . Luego, el programa se distribuye en esa forma binaria, pero no en forma de código fuente. En la máquina del usuario, ese bytecode se introduce en una nueva entidad: la máquina virtual , que de hecho interpreta ese bytecode. Debido a esto, las máquinas virtuales también se llaman intérprete de bytecode . ¡Pero pon tu atención aquí! Un intérprete clásico es unintérprete de texto , pero una máquina virtual es un intérprete binario ! Este es un enfoque adoptado por Java y C #.

Finalmente, si agregamos la generación de código de máquina al compilador de bytecode, logramos como resultado lo que llamamos un compilador clásico . Un compilador clásico convierte el código fuente del programa en el código de máquina de un procesador en particular. Ese código de máquina se puede ejecutar directamente en el procesador de destino sin ninguna mediación adicional (sin ningún tipo de intérprete ni intérprete de texto ni intérprete binario).

Ahora volvamos a la pregunta original y consideremos Java vs Python.

Inicialmente, Java se diseñó para tener la menor cantidad posible de dependencias de implementación. Su diseño se basa en el principio "escribir una vez, ejecutar en cualquier lugar" (WORA). Para implementarlo, Java se diseñó inicialmente como un lenguaje de programación que se compila en un código de bytes binario independiente de la máquina , que luego se puede ejecutar en todas las plataformas que admiten Java sin la necesidad de su recompilación. Puedes pensar en Java como en C ++ basado en WORA . En realidad, Java está más cerca de C ++ que de los lenguajes de script como Python . Pero en contraste con C ++ , Javafue diseñado para ser compilado en código de bytes binario que luego se ejecuta en el entorno de la máquina virtual , mientras que C ++ fue diseñado para ser compilado en código de máquina y luego directamente ejecutado por el procesador de destino.

Python se diseñó inicialmente como una especie de lenguaje de programación de scripts que interpreta scripts (programas en forma de texto escrito de acuerdo con las reglas del lenguaje de programación). Debido a esto, Python ha admitido inicialmente una interpretación dinámica de comandos o sentencias de una línea, como lo hacen Bash o Windows CMD. Por la misma razón, las implementaciones iniciales de Python no tenían ningún tipo de compiladores de bytecode y máquinas virtuales para la ejecución de dicho bytecode en el interior, pero desde el principio Python requirió un intérprete capaz de comprender y evaluar el texto del programa Python .

Debido a esto, históricamente, los desarrolladores de Java tienden a hablar sobre Java Virtual Machine (porque inicialmente, Java ha venido como un paquete de compilador de bytecode de Java e intérprete de bytecode - JVM ), y los desarrolladores de Python tienden a hablar sobre el intérprete de Python (porque inicialmente Python ha no era una máquina virtual y era una especie de intérprete de texto clásico que ejecuta el texto del programa directamente sin ningún tipo de compilación o transformación en ninguna forma de código binario).

Actualmente, Python también tiene la máquina virtual bajo el capó y puede compilar e interpretar el código de bytes de Python. Y ese hecho hace una inversión adicional en la confusión " ¿Por qué Java Virtual Machine, pero Python interprete?y que los programas demostrarán exactamente el mismo comportamiento y producirán igualmente la misma salida de la misma entrada. La única diferencia observable será la velocidad de ejecución del programa y la cantidad de memoria consumida por el intérprete. Por lo tanto, la máquina virtual en Python no es una parte inevitable del diseño del lenguaje, sino solo una extensión opcional del principal intérprete de Python.

Java puede considerarse de manera similar. Java bajo el capó tiene un compilador JIT y puede compilar selectivamente métodos de clase Java en el código de máquina de la plataforma de destino y luego ejecutarlo directamente. ¡Pero! Java todavía utiliza la interpretación de bytecode como una forma principal de ejecución del programa Java. Al igual que las implementaciones de Python que explotan máquinas virtuales bajo el capó exclusivamente como una técnica de optimización, las máquinas virtuales Java utilizan compiladores Just-In-Time exclusivamente para fines de optimización. Del mismo modo, solo por el hecho de que la ejecución directa del código de la máquina es al menos diez veces más rápida que la interpretación del código de bytes de Java. Y como en el caso de Python, la presencia del compilador JIT bajo el capó de JVM es absolutamente transparente tanto para los diseñadores de lenguaje Java como para los desarrolladores de programas Java. JVM puede implementar el mismo lenguaje de programación Java con y sin el compilador JIT. Y de la misma manera, se pueden ejecutar los mismos programas en JVM con y sin JIT dentro, y los mismos programas demostrarán exactamente el mismo comportamiento y producirán igualmente la misma salida de la entrada igual en ambas JVM (con y sin JIT). Y como en el caso de Python, la única diferencia observable entre ellos estará en la velocidad de ejecución y en la cantidad de memoria consumida por JVM. Y finalmente, como en el caso de Python, JIT en Java tampoco es una parte inevitable del diseño del lenguaje, sino solo una extensión opcional de las principales implementaciones de JVM. y los mismos programas demostrarán exactamente el mismo comportamiento y producirán igualmente la misma salida de la misma entrada en ambas JVM (con y sin JIT). Y como en el caso de Python, la única diferencia observable entre ellos estará en la velocidad de ejecución y en la cantidad de memoria consumida por JVM. Y finalmente, como en el caso de Python, JIT en Java tampoco es una parte inevitable del diseño del lenguaje, sino solo una extensión opcional de las principales implementaciones de JVM. y los mismos programas demostrarán exactamente el mismo comportamiento y producirán igualmente la misma salida de la misma entrada en ambas JVM (con y sin JIT). Y como en el caso de Python, la única diferencia observable entre ellos estará en la velocidad de ejecución y en la cantidad de memoria consumida por JVM. Y finalmente, como en el caso de Python, JIT en Java tampoco es una parte inevitable del diseño del lenguaje, sino solo una extensión opcional de las principales implementaciones de JVM.

Desde el punto de vista del diseño e implementación de máquinas virtuales de Java y Python, difieren significativamente, mientras que (¡atención!) Ambas siguen siendo máquinas virtuales. JVM es un ejemplo de una máquina virtual de bajo nivel con operaciones básicas simples y alto costo de envío de instrucciones. Python a su vez es una máquina virtual de alto nivel, para la cual las instrucciones demuestran un comportamiento complejo, y el costo de envío de instrucciones no es tan significativo. Java opera con un nivel de abstracción muy bajo. JVM opera en el pequeño conjunto bien definido de tipos primitivos y tiene una correspondencia muy estrecha (generalmente uno a uno) entre las instrucciones de código de bytes y las instrucciones de código de máquina nativa. Por el contrario, la máquina virtual Python opera a un alto nivel de abstracción, opera con tipos de datos complejos (objetos) y admite polimorfismo ad-hoc, mientras que las instrucciones de código de bytes exponen un comportamiento complejo, que puede ser representado por una serie de múltiples instrucciones de código de máquina nativas. Por ejemplo, Python admite matemáticas de rango ilimitado. Por lo tanto, Python VM se ve obligado a explotar aritmética larga para enteros potencialmente grandes para los cuales el resultado de la operación puede desbordar la palabra máquina. Por lo tanto, una instrucción de bytecode para aritmética en Python puede exponerse en la llamada de función dentro de Python VM, mientras que en JVM la operación aritmética expondrá en una operación simple expresada por una o pocas instrucciones de máquina nativas. Por lo tanto, Python VM se ve obligado a explotar aritmética larga para enteros potencialmente grandes para los cuales el resultado de la operación puede desbordar la palabra máquina. Por lo tanto, una instrucción de código de bytes para aritmética en Python puede exponerse en la llamada de función dentro de Python VM, mientras que en JVM la operación aritmética expondrá en una operación simple expresada por una o pocas instrucciones de máquina nativas. Por lo tanto, Python VM se ve obligado a explotar aritmética larga para enteros potencialmente grandes para los cuales el resultado de la operación puede desbordar la palabra máquina. Por lo tanto, una instrucción de código de bytes para aritmética en Python puede exponerse en la llamada de función dentro de Python VM, mientras que en JVM la operación aritmética expondrá en una operación simple expresada por una o pocas instrucciones de máquina nativas.

Como resultado, podemos sacar las siguientes conclusiones. Máquina virtual Java pero el intérprete de Python se debe a que:

  1. El término de máquina virtual supone la interpretación del código de bytes binario, mientras que el término intérprete supone la interpretación del texto del programa.
  2. Históricamente, Java fue diseñado e implementado para la interpretación de código de bytes binario y Python fue inicialmente diseñado e implementado para la interpretación de texto del programa. Por lo tanto, el término "Máquina virtual Java" es histórico y está bien establecido en la comunidad Java. Y de manera similar, el término "intérprete de Python" es histórico y está bien establecido en la comunidad de Python. Los pueblos tienden a prolongar la tradición y usan los mismos términos que se usaron mucho antes.
  3. Finalmente, actualmente, para Java, la interpretación de código de bytes binario es una forma principal de ejecución de programas, mientras que la compilación JIT es solo una optimización opcional y transparente. Y para Python, actualmente, la interpretación del texto del programa es una forma principal de ejecución de los programas de Python, mientras que la compilación en el código de bytes de Python VM es solo una optimización opcional y transparente.

Por lo tanto, tanto Java como Python tienen máquinas virtuales que son intérpretes de código de bytes binarios, lo que puede generar confusión como " ¿Por qué Java Virtual Machine, pero Python interprete?". El punto clave aquí es que para Python, una máquina virtual no es un medio primario o necesario para la ejecución del programa; es solo una extensión opcional del intérprete de texto clásico. Por otro lado, una máquina virtual es un núcleo e inevitable. parte del ecosistema de ejecución de programas Java. La elección de tipeo estático o dinámico para el diseño del lenguaje de programación afecta principalmente al nivel de abstracción de la máquina virtual solamente, pero no dicta si se necesita o no una máquina virtual. Los lenguajes que usan ambos sistemas de tipeo pueden diseñarse para ser compilados , interpretado o ejecutado dentro del entorno de la máquina virtual, dependiendo de su modelo de ejecución deseado.


2
Esto debería elegirse como la respuesta oficial en mi humilde opinión.
Ravikanth Andhavarapu

La respuesta oficial debería ser SÍ ya que "tanto Java como Python tienen máquinas virtuales que son intérpretes de código de bytes binarios". Período.
stuartw

10

No hay una diferencia real entre ellos, las personas simplemente siguen las convenciones que los creadores han elegido.


3
Te arrojaré un hueso aquí, ya que creo que esta es probablemente la respuesta real y te votaron por falta de bits.
vikingben

3

No olvide que Python tiene compiladores JIT disponibles para x86, lo que confunde aún más el problema. (Ver psicópata).

Una interpretación más estricta de un 'lenguaje interpretado' solo se vuelve útil cuando se discuten problemas de rendimiento de la VM, por ejemplo, en comparación con Python, Ruby se consideró (¿es?) Más lento porque es un lenguaje interpretado, a diferencia de Python, en otros Es decir, el contexto lo es todo.


1
Eso está mal. Primero, no existe un "lenguaje interpretado". Si una implementación usa un compilador o un intérprete no es un rasgo del lenguaje sino de la implementación. En segundo lugar, de las aproximadamente 13 implementaciones de Ruby, exactamente 1 es un intérprete, todas las demás tienen compiladores.
Jörg W Mittag el

2
Tercero, Ruby no es lento. Ningún idioma es lento, porque la velocidad no es un rasgo del idioma, sino la implementación del lenguaje. De las aproximadamente 13 implementaciones de Ruby, algunas son más lentas que algunas de las 7 implementaciones de Python, algunas son más rápidas.
Jörg W Mittag el

Creo que está comparando las implementaciones estándar aquí Jörg. CPython y Ruby (creo que la implementación oficial se llama Ruby).
James McMahon el

Si bien Arafangion podría estar refiriéndose a las implementaciones "estándar", debería haberlo dicho. Soy Pythonista, pero odio cualquier declaración de la forma "El lenguaje X es lento", ya que estoy de acuerdo con Jörg en materia de implementaciones.
tzot

1
Esto es exactamente por qué dije "was (is?)", Y particularmente el término "más lento". En ninguna parte dije que Ruby es en sí lento.
Arafangion

2

Python puede interpretar el código sin compilarlo en bytecode. Java no puede .

Python es un lenguaje interpretado, a diferencia de uno compilado, aunque la distinción puede ser borrosa debido a la presencia del compilador de bytecode. Esto significa que los archivos fuente se pueden ejecutar directamente sin crear explícitamente un ejecutable que luego se ejecuta.

(de la documentación).

En java, cada archivo tiene que compilarse en un .classarchivo, que luego se ejecuta en la JVM. Por el contrario, Python hace que sean importados por su script principal, para ayudar a acelerar los usos posteriores de esos archivos.

Sin embargo, en el caso típico, la mayoría del código python (al menos, CPython) se ejecuta en una máquina de pila emulada, que tiene instrucciones casi idénticas a las de la JVM, por lo que no hay una gran diferencia.

Sin embargo, la verdadera razón de la discreción es porque, desde el principio, Java se calificó a sí mismo como "código de bytes ejecutable portátil" y Python se calificó a sí mismo como lenguaje dinámico e interpretado con un REPL. Los nombres se pegan!


0

En primer lugar, debe comprender que la programación o la informática en general no son matemáticas y no tenemos definiciones rigurosas para la mayoría de los términos que usamos a menudo.

ahora a su pregunta:

¿Qué es un intérprete (en informática)

Traduce el código fuente por la unidad ejecutable más pequeña y luego ejecuta esa unidad.

que es una maquina virtual

en el caso de JVM, la máquina virtual es un software que contiene un intérprete, cargadores de clases, recolector de basura, programador de subprocesos, compilador JIT y muchas otras cosas.

como puede ver, el intérprete es una parte o una JVM y no se puede llamar a una JVM completa un intérprete porque contiene muchos otros componentes.

¿Por qué usar la palabra "intérprete" al hablar de Python?

con java la parte de compilación es explícita. Python, por otro lado, no es explícito como Java sobre su proceso de compilación e interpretación, desde la perspectiva del usuario final, la interpretación es el único mecanismo utilizado para ejecutar programas de Python.


0

No, ambos no interpretan el código de bytes.

Python solo interpreta bytecode si está ejecutando con pypy. De lo contrario, se compila en C y se interpreta a ese nivel.

Java compila a bytecode.


¿Puedes dar algún recurso a tu respuesta?
Isuru Dilshan


Esto es lo que está mal con Stack Overflow. Alguien tiene un ataque de enojo porque son llamados y lo expresan con votos negativos.
Michael Tamillow

0

Creo que las líneas entre ambos son borrosas, la mayoría de las personas discuten sobre el significado de la palabra "intérprete" y qué tan cerca está el lenguaje a cada lado del espectro "intérprete ... compilador". Sin embargo, ninguno gana el 100%. Creo que es fácil escribir la implementación de Java o Python que sea de cualquier valor del espectro.

Actualmente, tanto Java como Python tienen máquinas virtuales y código de bytes, aunque uno opera por tamaños de valor concretos (como un entero de 32 bits) mientras que otro tiene que determinar el tamaño de cada llamada, que en mi opinión no define el límite entre los términos.

El argumento de que Python no tiene bytecode oficialmente definido y existe solo en la memoria tampoco me convence, solo porque estoy planeando desarrollar dispositivos que reconozcan solo el bytecode de Python y la parte de compilación se realizará en la máquina JS del navegador.

El rendimiento solo se trata de la implementación concreta. No necesitamos saber el tamaño del objeto para poder trabajar con él, y finalmente, en la mayoría de los casos, trabajamos con estructuras, no con tipos básicos. Es posible optimizar Python VM de la manera que eliminará la necesidad de crear nuevos objetos cada vez durante el cálculo de la expresión, reutilizando uno existente. Una vez hecho esto, no existe una diferencia de rendimiento global entre el cálculo de la suma de dos enteros, que es donde brilla Java.

No hay una gran diferencia entre los dos, solo algunos matices de implementación y falta de optimización que son irrelevantes para el usuario final, tal vez en el punto en que comienza a notar retrasos en el rendimiento, pero nuevamente es un problema de implementación y no de arquitectura.


0

Para las publicaciones que mencionan que Python no necesita generar código de bytes, no estoy seguro de que sea cierto. parece que todas las llamadas en Python deben tener un .__code__.co_codeatributo que contenga el código de bytes. No veo una razón significativa para llamar a Python "no compilado" solo porque los artefactos compilados pueden no guardarse; y, a menudo, no se guardan por diseño en Python, por ejemplo, toda la compilación compila un nuevo bytecode para su entrada, esta es la razón por la que el alcance de la variable de comprensión no es coherente compile(mode='exec, ...)y compila compile(mode='single', ...), por ejemplo, entre ejecutar un script de Python y usar pdb

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.