Java «machine virtuelle» ou langage «interprète» Python?

207

Il semble rare de lire une "machine virtuelle" Python alors qu'en Java une "machine virtuelle" est utilisée tout le temps.

Les deux interprètent des codes d'octets; pourquoi appeler l'un une machine virtuelle et l'autre un interprète?

twils
la source

Réponses:

137

Une machine virtuelle est un environnement informatique virtuel avec un ensemble spécifique d'instructions atomiques bien définies qui sont prises en charge indépendamment de tout langage spécifique et elle est généralement considérée comme un bac à sable en soi. La machine virtuelle est analogue à un ensemble d'instructions d'un processeur spécifique et a tendance à fonctionner à un niveau plus fondamental avec des blocs de construction très basiques de telles instructions (ou codes d'octets) qui sont indépendants des suivants. Une instruction s'exécute de façon déterministe uniquement sur la base de l'état actuel de la machine virtuelle et ne dépend pas des informations ailleurs dans le flux d'instructions à ce moment.

Un interprète, d'autre part, est plus sophistiqué en ce qu'il est conçu pour analyser un flux d'une syntaxe qui est d'une langue spécifique et d'un grammaire spécifique qui doit être décodé dans le contexte des jetons environnants. Vous ne pouvez pas regarder chaque octet ou même chaque ligne isolément et savoir exactement quoi faire ensuite. Les jetons du langage ne peuvent pas être pris isolément comme ils le peuvent par rapport aux instructions (codes d'octets) d'une machine virtuelle.

Un compilateur Java convertit le langage Java en un flux de code octet pas différent d'un compilateur C convertit les programmes en langage C en code assembleur. Un interprète, d'autre part, ne convertit pas vraiment le programme en une forme intermédiaire bien définie, il prend simplement les actions du programme comme une question de processus d'interprétation de la source.

Un autre test de la différence entre une machine virtuelle et un interprète est de savoir si vous la considérez comme indépendante de la langue. Ce que nous savons comme la machine virtuelle Java n'est pas vraiment spécifique à Java. Vous pouvez créer un compilateur à partir d'autres langages qui produisent des codes octets pouvant être exécutés sur la JVM. D'un autre côté, je ne pense pas que nous penserions vraiment à "compiler" un autre langage autre que Python en Python pour une interprétation par l'interpréteur Python.

En raison de la sophistication du processus d'interprétation, cela peut être un processus relativement lent ... spécifiquement l'analyse et l'identification des jetons de langue, etc. et la compréhension du contexte de la source pour pouvoir entreprendre le processus d'exécution au sein de l'interpréteur. Pour aider à accélérer ces langages interprétés, c'est là que nous pouvons définir des formes intermédiaires de code source pré-analysé et pré-tokenisé qui est plus facilement interprété directement. Ce type de formulaire binaire est toujours interprété au moment de l'exécution, il ne fait que commencer à partir d'un formulaire beaucoup moins lisible par l'homme pour améliorer les performances. Cependant, la logique exécutant ce formulaire n'est pas une machine virtuelle, car ces codes ne peuvent toujours pas être pris isolément - le contexte des jetons environnants est toujours important, ils sont juste maintenant sous une forme différente plus efficace sur ordinateur.

Grand Jeff
la source
7
J'avais l'impression que python générait du code octet, pyc, ou est-ce que vous faites référence par "aide à accélérer de tels langages interprétés, c'est là que nous pouvons définir des formes intermédiaires de code source pré-analysé et pré-tokenisé qui est plus directement interprétée. "
James McMahon
32
@InSciTek Jeff: D'après votre réponse, il n'est pas clair si vous savez que Python utilise également une machine virtuelle.
tzot le
3
@TZ - L'implémentation Python populaire est un compilateur Python avec une machine virtuelle arrière. En mode interactif, c'est un peu hybride avec à la fois un frontal d'interpréteur et un backend de compilateur. Cependant, ce sont des choix de mise en œuvre. J'ai essayé de décrire la différence entre le concept de machine virtuelle et l'interprète
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.Il est possible d'écrire un langage qui peut être compilé en bytecode Python, tout comme Scala est compilé en bytecode Java. En mode interactif, le shell interactif de Python compile votre commande typée en bytecode et exécute ce bytecode. Vous pouvez écrire votre propre shell en utilisant eval et exec, et vous pouvez utiliser la fonction intégrée compile () pour transformer une chaîne en bytecode.
Lie Ryan
4
@Lie Ryan oui mais ce n'est pas officiellement pris en charge comme c'est le cas avec la JVM. En Python, le bytecode est un détail d'implémentation non documenté.
Antimony
159

Dans cet article, «machine virtuelle» fait référence aux machines virtuelles de processus, pas aux machines virtuelles système comme Qemu ou Virtualbox. Une machine virtuelle de processus est simplement un programme qui fournit un environnement de programmation général - un programme qui peut être programmé.

Java a un interprète ainsi qu'une machine virtuelle, et Python a une machine virtuelle ainsi qu'un interprète. La raison pour laquelle "machine virtuelle" est un terme plus courant en Java et "interprète" est un terme plus courant en Python a beaucoup à voir avec la différence majeure entre les deux langages: typage statique (Java) vs typage dynamique (Python). Dans ce contexte, "type" fait référence aux types de données primitifs - types qui suggèrent la taille de stockage en mémoire des données. La machine virtuelle Java est simple. Il nécessite que le programmeur spécifie le type de données primitif de chaque variable. Cela fournit des informations suffisantes pour que le bytecode Java soit non seulement interprété et exécuté par la machine virtuelle Java, mais même compilé en instructions machine. La machine virtuelle Python est plus complexe dans le sens où elle prend la tâche supplémentaire de faire une pause avant l'exécution de chaque opération pour déterminer les types de données primitifs pour chaque variable ou structure de données impliquée dans l'opération. Python libère le programmeur de la réflexion en termes de types de données primitifs et permet d'exprimer les opérations à un niveau supérieur. Le prix de cette liberté est la performance. "Interprète" est le terme préféré pour Python car il doit faire une pause pour inspecter les types de données, et aussi parce que la syntaxe relativement concise des langages typés dynamiquement convient bien aux interfaces interactives. Il n'y a pas d'obstacle technique à la construction d'une interface Java interactive, mais essayer d'écrire n'importe quel code de type statique de manière interactive serait fastidieux, donc ce n'est tout simplement pas fait de cette façon.

Dans le monde Java, la machine virtuelle vole la vedette car elle exécute des programmes écrits dans un langage qui peut en fait être compilé en instructions machine, et le résultat est la vitesse et l'efficacité des ressources. Le bytecode Java peut être exécuté par la machine virtuelle Java avec des performances proches de celles des programmes compilés, relativement parlant. Cela est dû à la présence d'informations de type de données primitives dans le bytecode. La machine virtuelle Java place Java dans une catégorie à part:

portable interprété de façon statique

La prochaine chose la plus proche est LLVM, mais LLVM fonctionne à un niveau différent:

langage d'assemblage interprété portable

Le terme "bytecode" est utilisé à la fois en Java et en Python, mais tous les bytecode ne sont pas créés égaux. bytecode est juste le terme générique pour les langages intermédiaires utilisés par les compilateurs / interprètes. Même les compilateurs C comme gcc utilisent un langage intermédiaire (ou plusieurs) pour faire le travail. Le bytecode Java contient des informations sur les types de données primitifs, contrairement au bytecode Python. À cet égard, la machine virtuelle Python (et Bash, Perl, Ruby, etc.) est vraiment fondamentalement plus lente que la machine virtuelle Java, ou plutôt, elle a simplement plus de travail à faire. Il est utile de considérer quelles informations sont contenues dans différents formats de bytecode:

  • llvm: registres cpu
  • Java: types de données primitifs
  • Python: types définis par l'utilisateur

Pour tirer une analogie du monde réel: LLVM fonctionne avec des atomes, la machine virtuelle Java fonctionne avec des molécules et La machine virtuelle Python fonctionne avec des matériaux. Puisque tout doit finalement se décomposer en particules subatomiques (opérations réelles de la machine), la machine virtuelle Python a la tâche la plus complexe.

Les interprètes / compilateurs de langues à typage statique n'ont tout simplement pas le même bagage que les interprètes / compilateurs de langues à typage dynamique. Les programmeurs de langages de type statique doivent prendre le relais, pour lequel le gain est la performance. Cependant, tout comme toutes les fonctions non déterministes sont secrètement déterministes, il en est de même pour toutes les langues à typage dynamique secrètement à typage statique. Les différences de performances entre les deux familles de langues devraient donc se stabiliser au moment où Python change son nom en HAL 9000.

Les machines virtuelles de langages dynamiques comme Python implémentent une machine logique idéalisée et ne correspondent pas nécessairement très étroitement à un matériel physique réel. La machine virtuelle Java, en revanche, est plus similaire en termes de fonctionnalités à un compilateur C classique, sauf qu'au lieu d'émettre des instructions machine, elle exécute des routines intégrées. En Python, un entier est un objet Python avec un tas d'attributs et de méthodes qui lui sont attachés. En Java, un int est un nombre désigné de bits, généralement 32. Ce n'est pas vraiment une comparaison juste. Les entiers Python doivent vraiment être comparés à la classe Java Integer. Le type de données primitif "int" de Java ne peut être comparé à rien dans le langage Python, car le langage Python n'a tout simplement pas cette couche de primitives, tout comme le bytecode Python.

Étant donné que les variables Java sont typées explicitement, on peut raisonnablement s'attendre à ce que quelque chose comme les performances Jython soient dans le même stade que cPython . D'un autre côté, une machine virtuelle Java implémentée en Python est presque garantie d'être plus lente que la boue. Et ne vous attendez pas à ce que Ruby, Perl, etc. s'en sortent mieux. Ils n'étaient pas conçus pour cela. Ils ont été conçus pour le "scripting", ce que l'on appelle la programmation dans un langage dynamique.

Chaque opération qui a lieu dans une machine virtuelle doit finalement toucher du matériel réel. Les machines virtuelles contiennent des routines précompilées qui sont suffisamment générales pour exécuter n'importe quelle combinaison d'opérations logiques. Une machine virtuelle peut ne pas émettre de nouvelles instructions machine, mais elle exécute certainement ses propres routines encore et encore dans des séquences arbitrairement complexes. La machine virtuelle Java, la machine virtuelle Python et toutes les autres machines virtuelles à usage général sont égales dans le sens où elles peuvent être amenées à exécuter n'importe quelle logique que vous pouvez imaginer, mais elles sont différentes en termes de tâches qu'elles assumer et quelles tâches ils laissent au programmeur.

Psyco pour Python n'est pas une machine virtuelle Python complète, mais un compilateur juste à temps qui détourne la machine virtuelle Python régulière à des moments où il pense pouvoir compiler quelques lignes de code - principalement des boucles où il pense que le type primitif de certains La variable restera constante même si la valeur change à chaque itération. Dans ce cas, il peut renoncer à une partie de la détermination de type incessant de la machine virtuelle régulière. Cependant, vous devez être un peu prudent, de peur de retirer le type sous les pieds de Psyco. Pysco, cependant, sait généralement se replier sur la machine virtuelle habituelle s'il n'est pas complètement sûr que le type ne changera pas.

La morale de l'histoire est que les informations de type de données primitives sont vraiment utiles pour un compilateur / une machine virtuelle.

Enfin, pour mettre tout cela en perspective, considérez ceci: un programme Python exécuté par un interprète / machine virtuelle Python implémenté en Java fonctionnant sur un interpréteur / machine virtuelle Java implémenté en LLVM fonctionnant sur une machine virtuelle qemu fonctionnant sur un iPhone.

permalien

pooryorick
la source
1
trying to write any statically-typed code interactively would be tedious. Si vous connaissez OCaml et Haskell, vous verrez que ce n'est pas vrai car ce sont des langages de type statique très concis.
Matthias Braun
@MatthiasBraun Je peux convenir que ces langages fonctionnels produisent du code concis mais cela ne signifie pas nécessairement qu'ils sont bien adaptés au mode interactif. Si OCaml et Haskell étaient typés dynamiquement comme lisp, ils fonctionneraient mieux pour le mode interactif je suppose.
bombes
58

L'une des raisons de la terminologie différente est probablement que l'on pense normalement à alimenter l'interpréteur python en code source lisible par l'homme et à ne pas se soucier du bytecode et tout cela.

En Java, vous devez explicitement compiler en bytecode, puis exécuter uniquement le bytecode, pas le code source sur la machine virtuelle.

Même si Python utilise une machine virtuelle sous les couvertures, du point de vue de l'utilisateur, on peut ignorer ce détail la plupart du temps.

Mr Fooz
la source
1
Je suis d'accord. Cette différence de terminologie se résume vraiment à l'expérience de l'utilisateur final (développeur, c'est-à-dire). Cela n'a rien à voir avec de réelles différences techniques, car la ligne technique est si incroyablement floue qu'elle est presque inexistante.
Cody Brocious
1
+1: Et - plus important encore - quel est l'intérêt? Quel programme ne pouvez-vous pas écrire à cause de cette distinction? Quelle trace de pile vous déroute? Quelle bibliothèque ne semble pas fonctionner correctement?
S.Lott
@ S.Lott Parce qu'il est toujours bon de gagner des disputes avec ses collègues. ;)
Qix - MONICA A ETE BRUTEE
16

Interprète , traduit le code source en une représentation intermédiaire efficace (code) et l'exécute immédiatement.

Virtual Machine , exécute explicitement le code précompilé stocké construit par un compilateur qui fait partie du système d'interpréteur.

Une caractéristique très importante d'une machine virtuelle est que le logiciel s'exécutant à l'intérieur est limité aux ressources fournies par la machine virtuelle. Précisément, il ne peut pas sortir de son monde virtuel. Pensez à l'exécution sécurisée du code distant, les applets Java.

En cas de python, si nous conservons des fichiers pyc , comme mentionné dans le commentaire de ce post, alors le mécanisme deviendrait plus comme une machine virtuelle, et ce bytecode s'exécute plus rapidement - il serait toujours interprété mais à partir d'une forme beaucoup plus conviviale pour l'ordinateur . Si nous regardons cela dans son ensemble, PVM est une dernière étape de Python Interpreter.

L'essentiel est que, lorsque vous référez à Python Interpreter, cela signifie que nous le référons dans son ensemble, et lorsque nous disons PVM, cela signifie que nous parlons simplement d'une partie de Python Interpreter, un environnement d'exécution. Semblable à celui de Java, nous référons différentes parties differentyl, JRE, JVM, JDK, etc.

Pour en savoir plus, Wikipédia: interprète et machine virtuelle . Encore un autre ici . Ici vous pouvez trouver la comparaison des machines virtuelles d'application . Il aide à comprendre la différence entre les compilateurs, les interprètes et les machines virtuelles.

Adeel Ansari
la source
12

Le terme interpréteur est un terme hérité remontant aux langages de script shell antérieurs. Au fur et à mesure que les "langages de script" sont devenus des langages complets et que leurs plates-formes correspondantes sont devenues plus sophistiquées et en bac à sable, la distinction entre une machine virtuelle et un interprète (au sens Python) est très petite ou inexistante.

L'interpréteur Python fonctionne toujours de la même manière qu'un script shell, en ce sens qu'il peut être exécuté sans étape de compilation distincte. Au-delà de cela, les différences entre l'interpréteur Python (ou Perl ou Ruby) et la machine virtuelle Java sont principalement des détails d'implémentation. (On pourrait faire valoir que Java est plus entièrement en sandbox que Python, mais les deux fournissent finalement un accès à l'architecture sous-jacente via une interface C native.)

Daniel Naab
la source
1
il existe des shells java qui peuvent exécuter du code java sans étapes de compilation distinctes (visibles par l'utilisateur).
Lie Ryan
1
donnez-moi le nom: D
Maciej Nowicki
11

Pour répondre en profondeur à la question " Pourquoi Java Virtual Machine, mais l'interpréteur Python? ", Essayons de revenir au domaine de la théorie de la compilation quant au point de départ de la discussion.

Le processus typique de compilation de programme comprend les étapes suivantes:

  1. Analyse lexicale . Divise le texte du programme en "mots" significatifs appelés jetons (dans le cadre du processus, tous les commentaires, espaces, nouvelles lignes, etc. sont supprimés, car ils n'affectent pas le comportement du programme). Le résultat est un flux ordonné de jetons.
  2. Analyse syntaxique . Construit le soi-disant arbre de syntaxe abstraite (AST) à partir du flux de jetons. AST établit des relations entre les jetons et, en conséquence, définit un ordre d'évaluation du programme.
  3. Analyse sémantique . Vérifie l'exactitude sémantique de l'AST en utilisant des informations sur les types et un ensemble de règles sémantiques du langage de programmation. (Par exemple, a = b + cest une déclaration correcte du point de vue de la syntaxe, mais complètement incorrecte du point de vue sémantique si elle a aété déclarée comme un objet constant)
  4. Génération de code intermédiaire . Sérialise AST dans le flux ordonné linéairement d'opérations "primitives" indépendantes de la machine. En fait, le générateur de code traverse AST et enregistre l'ordre des étapes d'évaluation. Par conséquent, à partir de la représentation arborescente du programme, nous obtenons une représentation de type liste beaucoup plus simple dans laquelle l'ordre d'évaluation du programme est préservé.
  5. Génération de code machine . Le programme sous la forme d'un bytecode "primitif" indépendant de la machine est traduit en code machine d'une architecture de processeur particulière.

D'accord. Définissons maintenant les termes.

L'interprète , au sens classique de ce mot, suppose une exécution basée sur l'évaluation du programme basée sur l'AST produite directement à partir du texte du programme . Dans ce cas, un programme est distribué sous forme de code source et l'interpréteur est alimenté par le texte du programme, souvent de manière dynamique (instruction par instruction ou ligne par ligne). Pour chaque instruction d'entrée, l'interpréteur construit son AST et l'évalue immédiatement en changeant "l'état" du programme. Il s'agit d'un comportement typique démontré par les langages de script. Considérez par exemple Bash, Windows CMD etc. Conceptuellement, Python prend également cette voie.

Si nous remplaçons l'étape d'exécution basée sur AST sur la génération d'une étape intermédiaire de bytecode binaire indépendante de la machine dans l'interpréteur, nous diviserons l'ensemble du processus d'exécution du programme en deux phases distinctes: compilation et exécution. Dans ce cas, ce qui était auparavant un interpréteur deviendra un compilateur de bytecode, qui transformera le programme de la forme du texte en une forme binaire . Ensuite, le programme est distribué sous cette forme binaire, mais pas sous la forme de code source. Sur la machine utilisateur, ce bytecode est introduit dans une nouvelle entité - la machine virtuelle , qui en fait interprète ce bytecode. Pour cette raison, les machines virtuelles sont également appelées interprètes de bytecode . Mais mettez votre attention ici! Un interprète classique est uninterpréteur de texte , mais une machine virtuelle est un interprète binaire ! Il s'agit d'une approche adoptée par Java et C #.

Enfin, si nous ajoutons la génération de code machine au compilateur de bytecode, nous obtenons en résultat ce que nous appelons un compilateur classique . Un compilateur classique convertit le code source du programme en code machine d'un processeur particulier. Ce code machine peut alors être directement exécuté sur le processeur cible sans aucune médiation supplémentaire (sans aucun type d'interprète ni interprète de texte ni interprète binaire).

Revenons maintenant à la question d'origine et considérons Java vs Python.

Java a été initialement conçu pour avoir le moins de dépendances d'implémentation possible. Sa conception est basée sur le principe "écrire une fois, courir n'importe où" (WORA). Pour l'implémenter, Java a été initialement conçu comme un langage de programmation qui se compile en bytecode binaire indépendant de la machine , qui peut ensuite être exécuté sur toutes les plates-formes qui prennent en charge Java sans avoir besoin de sa recompilation. Vous pouvez penser à Java comme au C ++ basé sur WORA . En fait, Java est plus proche de C ++ que des langages de script comme Python . Mais contrairement à C ++ , Javaa été conçu pour être compilé en bytecode binaire qui est ensuite exécuté dans l'environnement de la machine virtuelle , tandis que C ++ a été conçu pour être compilé en code machine puis directement exécuté par le processeur cible.

Python a été initialement conçu comme une sorte de langage de programmation de script qui interprète les scripts (programmes sous la forme du texte écrit conformément aux règles du langage de programmation). Pour cette raison, Python a initialement pris en charge une interprétation dynamique des commandes ou des instructions sur une ligne, comme le font Bash ou Windows CMD. Pour la même raison, les implémentations initiales de Python n'avaient aucun type de compilateurs de bytecode et de machines virtuelles pour l'exécution de ce bytecode à l'intérieur, mais depuis le début, Python avait besoin d'un interprète capable de comprendre et d'évaluer le texte du programme Python .

Pour cette raison, historiquement, les développeurs Java avaient tendance à parler de machine virtuelle Java (car initialement, Java est venu comme un package de compilateur de bytecode Java et d' interpréteur de bytecode - JVM ), et les développeurs de Python avaient tendance à parler d' interpréteur Python (car initialement Python a pas n'importe quelle machine virtuelle et était une sorte d' interpréteur de texte classique qui exécute directement le texte du programme sans aucune sorte de compilation ou de transformation en n'importe quelle forme de code binaire).

Actuellement, Python a également la machine virtuelle sous le capot et peut compiler et interpréter le bytecode Python. Et ce fait fait un investissement supplémentaire dans la confusion " Pourquoi Java Virtual Machine, mais Python interpreter?et que les programmes démontreront exactement le même comportement et produiront également la même sortie à partir de l'entrée égale. La seule différence observable sera la vitesse d'exécution du programme et la quantité de mémoire consommée par l'interpréteur. Ainsi, la machine virtuelle en Python n'est pas une partie inévitable de la conception du langage, mais juste une extension facultative de l'interpréteur Python majeur.

Java peut être considéré de la même manière. Java sous le capot dispose d'un compilateur JIT et peut sélectivement compiler des méthodes de classe Java dans le code machine de la plate-forme cible, puis l'exécuter directement. Mais! Java utilise toujours l'interprétation du bytecode comme principal moyen d'exécution du programme Java. Comme les implémentations Python qui exploitent les machines virtuelles sous le capot exclusivement comme technique d'optimisation, les machines virtuelles Java utilisent des compilateurs Just-In-Time exclusivement à des fins d'optimisation. De même, juste parce que l'exécution directe du code machine est au moins dix fois plus rapide que l'interprétation du bytecode Java. Et comme dans le cas de Python, la présence du compilateur JIT sous le capot de JVM est absolument transparente pour les concepteurs de langage Java et les développeurs de programmes Java. Le même langage de programmation Java peut être implémenté par JVM avec et sans compilateur JIT. Et de la même manière, les mêmes programmes peuvent être exécutés dans des JVM avec et sans JIT à l'intérieur, et les mêmes programmes démontreront exactement le même comportement et produiront également la même sortie à partir de l'entrée égale sur les deux JVM (avec et sans JIT). Et comme dans le cas de Python, la seule différence observable entre eux, sera dans la vitesse d'exécution et dans la quantité de mémoire consommée par JVM. Et enfin, comme dans le cas de Python, JIT en Java n'est pas non plus une partie inévitable de la conception du langage, mais juste une extension facultative des principales implémentations JVM. et les mêmes programmes démontreront exactement le même comportement et produiront également la même sortie à partir de l'entrée égale sur les deux JVM (avec et sans JIT). Et comme dans le cas de Python, la seule différence observable entre eux, sera dans la vitesse d'exécution et dans la quantité de mémoire consommée par JVM. Et enfin, comme dans le cas de Python, JIT en Java n'est pas non plus une partie inévitable de la conception du langage, mais juste une extension facultative des principales implémentations JVM. et les mêmes programmes démontreront exactement le même comportement et produiront également la même sortie à partir de l'entrée égale sur les deux JVM (avec et sans JIT). Et comme dans le cas de Python, la seule différence observable entre eux, sera dans la vitesse d'exécution et dans la quantité de mémoire consommée par JVM. Et enfin, comme dans le cas de Python, JIT en Java n'est pas non plus une partie inévitable de la conception du langage, mais juste une extension facultative des principales implémentations JVM.

Du point de vue de la conception et de la mise en œuvre des machines virtuelles Java et Python, elles diffèrent considérablement, tandis que (attention!) Les deux restent toujours des machines virtuelles. JVM est un exemple de machine virtuelle de bas niveau avec des opérations de base simples et un coût d'envoi d'instructions élevé. Python est à son tour une machine virtuelle de haut niveau, pour laquelle les instructions démontrent un comportement complexe, et le coût de répartition des instructions n'est pas si important. Java fonctionne avec un niveau d'abstraction très bas. La JVM fonctionne sur le petit ensemble bien défini de types primitifs et a une correspondance très étroite (généralement une à une) entre les instructions de bytecode et les instructions de code machine natif. Au contraire, la machine virtuelle Python fonctionne à un niveau d'abstraction élevé, elle fonctionne avec des types de données complexes (objets) et prend en charge le polymorphisme ad hoc, tandis que les instructions de bytecode exposent un comportement complexe, qui peut être représenté par une série d'instructions de code machine natives multiples. Par exemple, Python prend en charge les mathématiques de plage illimitées. Ainsi, Python VM est obligé d'exploiter de longues arithmétiques pour des entiers potentiellement grands pour lesquels le résultat de l'opération peut déborder le mot machine. Par conséquent, une instruction de bytecode pour l'arithmétique en Python peut exposer dans l'appel de fonction à l'intérieur de Python VM, tandis que dans l'opération arithmétique JVM exposera en opération simple exprimée par une ou quelques instructions machine natives. Ainsi, Python VM est obligé d'exploiter de longues arithmétiques pour des entiers potentiellement grands pour lesquels le résultat de l'opération peut déborder le mot machine. Par conséquent, une instruction de bytecode pour l'arithmétique en Python peut exposer dans l'appel de fonction à l'intérieur de Python VM, tandis que dans l'opération arithmétique JVM exposera en opération simple exprimée par une ou quelques instructions machine natives. Ainsi, Python VM est obligé d'exploiter de longues arithmétiques pour des entiers potentiellement grands pour lesquels le résultat de l'opération peut déborder le mot machine. Par conséquent, une instruction de bytecode pour l'arithmétique en Python peut exposer dans l'appel de fonction à l'intérieur de Python VM, tandis que dans l'opération arithmétique JVM exposera en opération simple exprimée par une ou quelques instructions machine natives.

En conséquence, nous pouvons tirer les prochaines conclusions. Java Virtual Machine mais l'interpréteur Python est parce que:

  1. Le terme de machine virtuelle suppose une interprétation de bytecode binaire, tandis que le terme interprète suppose une interprétation de texte de programme.
  2. Historiquement, Java a été conçu et implémenté pour l'interprétation des bytecodes binaires et Python a été initialement conçu et implémenté pour l'interprétation du texte du programme. Ainsi, le terme «machine virtuelle Java» est historique et bien établi dans la communauté Java. Et de même, le terme "Python Interpreter" est historique et bien établi dans la communauté Python. Les peuples ont tendance à prolonger la tradition et à utiliser les mêmes termes qui étaient utilisés bien avant.
  3. Enfin, actuellement, pour Java, l'interprétation de bytecode binaire est un moyen principal d'exécution de programmes, tandis que la compilation JIT est juste une optimisation optionnelle et transparente. Et pour Python, actuellement, l'interprétation du texte du programme est un moyen principal d'exécution des programmes Python, tandis que la compilation dans le bytecode Python VM est juste une optimisation facultative et transparente.

Par conséquent, Java et Python ont des machines virtuelles qui sont des interprètes de bytecode binaire, ce qui peut conduire à des confusions telles que « Pourquoi Java Virtual Machine, mais interprète Python?". Le point clé ici est que pour Python, une machine virtuelle n'est pas un moyen principal ou nécessaire d'exécution de programme; c'est juste une extension facultative de l'interpréteur de texte classique. D'autre part, une machine virtuelle est un noyau et inévitable fait partie de l'écosystème d'exécution de programmes Java. Le choix de typage statique ou dynamique pour la conception du langage de programmation affecte principalement le niveau d'abstraction de la machine virtuelle uniquement, mais ne détermine pas si une machine virtuelle est nécessaire ou non. Les langues utilisant les deux systèmes de typage peuvent être conçues pour être compilées , interprétés ou exécutés dans l'environnement de la machine virtuelle, selon le modèle d'exécution souhaité.

ZarathustrA
la source
2
Cela devrait être choisi comme réponse officielle à mon humble avis.
Ravikanth Andhavarapu
La réponse officielle devrait être OUI car "Java et Python ont des machines virtuelles qui sont des interprètes de bytecode binaires". Période.
stuartw
10

Il n'y a pas vraiment de différence entre eux, les gens suivent simplement les conventions choisies par les créateurs.

Cody Brocious
la source
3
Je vais vous jeter un os ici car je pense que c'est probablement la vraie réponse et vous avez voté par manque de bits.
vikingben
3

N'oubliez pas que Python dispose de compilateurs JIT disponibles pour x86, ce qui complique encore le problème. (Voir psyco).

Une interprétation plus stricte d'un `` langage interprété '' ne devient utile que lorsque l'on discute des problèmes de performances de la machine virtuelle, par exemple, par rapport à Python, Ruby a été (est?) Considéré comme plus lent car il s'agit d'un langage interprété, contrairement à Python - dans d'autres mots, le contexte est tout.

Arafangion
la source
1
C'est faux. Premièrement, il n’existe pas de «langage interprété». Qu'une implémentation utilise un compilateur ou un interpréteur n'est pas un trait du langage mais de l'implémentation. Deuxièmement, sur les 13 implémentations Ruby, exactement 1 est un interprète, toutes les autres ont des compilateurs.
Jörg W Mittag
2
Troisièmement, Ruby n'est pas lent. Aucune langue n'est lente, car la vitesse n'est pas un trait de la langue, mais l'implémentation de la langue. Parmi les 13 implémentations Ruby, certaines sont plus lentes que certaines des 7 implémentations Python, certaines sont plus rapides.
Jörg W Mittag
Je pense qu'il compare les implémentations standard ici Jörg. CPython et Ruby (je pense que l'implémentation officielle est juste nommée Ruby).
James McMahon
Bien qu'Arafangion fasse peut-être référence aux implémentations "standard", il aurait dû le dire. Je suis pythoniste mais je déteste toute déclaration de la forme "Le langage X est lent", car je suis d'accord avec Jörg sur la question des implémentations.
tzot le
1
C'est exactement pourquoi j'ai dit "était (est?)", Et en particulier le terme "plus lent". Je n'ai dit nulle part que Ruby est en soi lente.
Arafangion
2

Python peut interpréter le code sans le compiler en bytecode. Java ne peut pas .

Python est un langage interprété, par opposition à un langage compilé, bien que la distinction puisse être floue en raison de la présence du compilateur de bytecode. Cela signifie que les fichiers source peuvent être exécutés directement sans créer explicitement un exécutable qui est ensuite exécuté.

(à partir de la documentation).

En java, chaque fichier doit être compilé dans un .classfichier, qui s'exécute ensuite sur la JVM. Au contraire, python fait ce qui est importé par votre script principal, pour aider à accélérer les utilisations ultérieures de ces fichiers.

Cependant, dans le cas typique, la plupart du code python (au moins, CPython) s'exécute dans une machine de pile émulée, qui a des instructions presque identiques à celles de la JVM, il n'y a donc pas de grande différence.

La vraie raison de la distorsion est cependant parce que, dès le début, java s'est marqué comme "bytecode portable et exécutable" et python s'est présenté comme un langage dynamique et interprété avec un REPL. Les noms collent!

note bleue
la source
0

Tout d'abord, vous devez comprendre que la programmation ou l'informatique en général ne sont pas des mathématiques et nous n'avons pas de définitions rigoureuses pour la plupart des termes que nous utilisons souvent.

maintenant à votre question:

qu'est-ce qu'un interprète (en informatique)

Il traduit le code source par la plus petite unité exécutable, puis exécute cette unité.

qu'est-ce qu'une machine virtuelle

dans le cas de JVM, la machine virtuelle est un logiciel qui contient un interpréteur, des chargeurs de classe, un garbage collector, un planificateur de threads, un compilateur JIT et bien d'autres choses.

comme vous pouvez le voir, l'interpréteur est une partie ou JVM et la JVM entière ne peut pas être appelée interprète car elle contient de nombreux autres composants.

pourquoi utiliser le mot "interprète" quand on parle de python

avec java, la partie compilation est explicite. python, d'autre part, n'est pas explicite en tant que java à propos de son processus de compilation et d'interprétation, du point de vue de l'utilisateur final, l'interprétation est le seul mécanisme utilisé pour exécuter des programmes python

mightyWOZ
la source
0

Non, ils n'interprètent pas tous les deux du code d'octet.

Python n'interprète le bytecode que si vous exécutez avec pypy. Sinon, il est compilé en C et interprété à ce niveau.

Java se compile en bytecode.

Michael Tamillow
la source
Pouvez-vous donner des ressources à votre réponse?
Isuru Dilshan
et c'est sur Java: en.wikipedia.org/wiki/Java_virtual_machine
Michael Tamillow
C'est ce qui ne va pas avec Stack Overflow. Quelqu'un a une crise de colère parce qu'il est appelé et l'exprime avec des votes négatifs.
Michael Tamillow
0

Je pense que les frontières entre les deux sont floues, les gens discutent principalement autour du sens du mot "interprète" et de la proximité de la langue de chaque côté du spectre "interprète ... compilateur". Aucun ne fait cependant 100%. Je pense qu'il est facile d'écrire une implémentation Java ou Python qui soit de n'importe quelle valeur du spectre.

Actuellement, Java et Python ont des machines virtuelles et du bytecode, bien que l'un fonctionne par des tailles de valeur concrètes (comme un entier 32 bits) tandis que l'autre doit déterminer la taille de chaque appel, ce qui, à mon avis, ne définit pas la frontière entre les termes.

L'argument selon lequel Python n'a pas de bytecode officiellement défini et qu'il n'existe qu'en mémoire ne me convainc pas non plus, simplement parce que je prévois de développer des appareils qui ne reconnaîtront que le bytecode Python et la partie de compilation se fera dans la machine JS du navigateur.

La performance ne concerne que la mise en œuvre concrète. Nous n'avons pas besoin de connaître la taille de l'objet pour pouvoir travailler avec lui, et enfin, dans la plupart des cas, nous travaillons avec des structures, pas des types basiques. Il est possible d'optimiser Python VM de manière à éliminer la nécessité de créer à chaque fois un nouvel objet lors du calcul de l'expression, en réutilisant un objet existant. Une fois cela fait, il n'y a pas de différence de performance globale entre le calcul de la somme de deux entiers, où Java brille.

Il n'y a pas de différence entre les deux, seulement quelques nuances d'implémentation et un manque d'optimisation qui ne sont pas pertinents pour l'utilisateur final, peut-être au point où elle commence à remarquer des décalages de performances, mais encore une fois, c'est un problème d'implémentation et non d'architecture.

Oleg Gordeev
la source
0

pour les articles qui mentionnent que python n'a pas besoin de générer de code d'octet, je ne suis pas sûr que ce soit vrai. il semble que tous les callables en Python doivent avoir un .__code__.co_codeattribut qui contient le code d'octet. Je ne vois pas de raison valable d'appeler python "non compilé" simplement parce que les artefacts compilés peuvent ne pas être enregistrés; et souvent ne sont pas enregistrés par conception en Python, par exemple toute la compréhension compile un nouveau bytecode pour son entrée, c'est la raison pour laquelle la portée de la variable de compréhension n'est pas cohérente entre compile(mode='exec, ...)et compile, compile(mode='single', ...)par exemple entre l'exécution d'un script python et l'utilisation de pdb

ThorSummoner
la source