Java "Virtual Machine" vs. Python "Interpreter" parlance?


207

Sembra raro leggere una "macchina virtuale" di Python mentre in Java "macchina virtuale" viene usata continuamente.

Entrambi interpretano i codici byte; perché chiamare uno una macchina virtuale e l'altro un interprete?

Risposte:


137

Una macchina virtuale è un ambiente di elaborazione virtuale con un set specifico di istruzioni atomiche ben definite che sono supportate indipendentemente da qualsiasi linguaggio specifico ed è generalmente considerata una sandbox a sé stante. La VM è analoga a un set di istruzioni di una CPU specifica e tende a funzionare a un livello più fondamentale con blocchi di base molto basilari di tali istruzioni (o codici byte) che sono indipendenti dal successivo. Un'istruzione viene eseguita in modo deterministico solo in base allo stato corrente della macchina virtuale e non dipende dalle informazioni altrove nel flusso di istruzioni in quel momento.

Un interprete invece è più sofisticato in quanto è su misura per analizzare un flusso di una sintassi che è di una lingua specifica e di una grammatica specifica che deve essere decodificata nel contesto dei token circostanti. Non puoi guardare ogni byte o anche ogni riga in isolamento e sapere esattamente cosa fare dopo. I token nella lingua non possono essere presi separatamente come possono fare relativamente alle istruzioni (codici byte) di una VM.

Un compilatore Java converte il linguaggio Java in un flusso di codice byte non diverso da un compilatore C converte i programmi in linguaggio C in codice assembly. D'altra parte, un interprete non converte realmente il programma in una forma intermedia ben definita, prende semplicemente le azioni del programma come una questione del processo di interpretazione della fonte.

Un altro test della differenza tra una macchina virtuale e un interprete è se la consideri indipendente dalla lingua. Ciò che conosciamo come Java VM non è proprio Java specifico. È possibile creare un compilatore da altre lingue che si traduca in codici byte che possono essere eseguiti sulla JVM. D'altra parte, non penso che penseremmo davvero di "compilare" un altro linguaggio diverso da Python in Python per l'interpretazione dell'interprete Python.

A causa della raffinatezza del processo di interpretazione, questo può essere un processo relativamente lento .... in particolare analizzare e identificare i token linguistici, ecc. E comprendere il contesto della fonte per essere in grado di intraprendere il processo di esecuzione all'interno dell'interprete. Per aiutare ad accelerare tali linguaggi interpretati, è qui che possiamo definire forme intermedie di codice sorgente pre-analizzato e pre-token che viene interpretato più facilmente direttamente. Questo tipo di forma binaria è ancora interpretata al momento dell'esecuzione, è solo a partire da una forma leggibile molto meno umana per migliorare le prestazioni. Tuttavia, la logica che esegue quel modulo non è una macchina virtuale, poiché quei codici non possono ancora essere presi in modo isolato: il contesto dei token circostanti è ancora importante, in questo momento sono in una forma diversa più efficiente dal punto di vista del computer.


7
Ho avuto l'impressione che Python abbia generato codice byte, pyc o che ciò a cui ti riferisci "aiuti ad accelerare tali linguaggi interpretati, è qui che possiamo definire forme intermedie di codice sorgente pre-analizzato e pre-tokenizzato che è più prontamente interpretato direttamente ".
James McMahon,

32
@InSciTek Jeff: Dalla tua risposta non è chiaro se sai che anche Python usa una macchina virtuale.
martedì

3
@TZ - La popolare implementazione di Python è un compilatore Python con una VM sul retro. In modalità interattiva, è un po 'ibrido con un front-end di interprete e un back-end del compilatore. Tuttavia, queste sono scelte di implementazione. Ho cercato di descrivere la differenza tra il concetto di VM e l'interprete
Jeff alto

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.È possibile scrivere un linguaggio che può essere compilato in bytecode Python, proprio come Scala è compilato in bytecode Java. In modalità interattiva, la shell interattiva di Python compila il tuo comando digitato in bytecode ed esegue quel bytecode. Puoi scrivere la tua shell usando eval ed exec e puoi usare la funzione integrata compile () per trasformare una stringa in bytecode.
Lie Ryan,

4
@Lie Ryan sì, ma non è ufficialmente supportato come lo è con la JVM. In Python, bytecode è un dettaglio dell'implementazione non documentato.
Antimonio

159

In questo post, "macchina virtuale" si riferisce a macchine virtuali di processo, non a macchine virtuali di sistema come Qemu o Virtualbox. Una macchina virtuale di processo è semplicemente un programma che fornisce un ambiente di programmazione generale, un programma che può essere programmato.

Java ha un interprete e una macchina virtuale, e Python ha una macchina virtuale e un interprete. Il motivo per cui "macchina virtuale" è un termine più comune in Java e "interprete" è un termine più comune in Python ha molto a che fare con la principale differenza tra i due linguaggi: la tipizzazione statica (Java) rispetto alla tipizzazione dinamica (Python). In questo contesto, "tipo" si riferisce a tipi di dati primitivi - tipi che suggeriscono la dimensione della memoria in memoria dei dati. La macchina virtuale Java è facile. Richiede al programmatore di specificare il tipo di dati primitivo di ciascuna variabile. Ciò fornisce informazioni sufficienti per il bytecode Java non solo per essere interpretato ed eseguito dalla macchina virtuale Java, ma anche per essere compilato nelle istruzioni della macchina. La macchina virtuale Python è più complessa, nel senso che assume il compito aggiuntivo di mettere in pausa prima dell'esecuzione di ciascuna operazione per determinare i tipi di dati primitivi per ciascuna variabile o struttura di dati coinvolta nell'operazione. Python libera il programmatore dal pensare in termini di tipi di dati primitivi e consente di esprimere le operazioni a un livello superiore. Il prezzo di questa libertà è la prestazione. "Interprete" è il termine preferito per Python perché deve fare una pausa per ispezionare i tipi di dati e anche perché la sintassi relativamente concisa dei linguaggi tipizzati dinamicamente si adatta bene alle interfacce interattive. Non ci sono ostacoli tecnici alla creazione di un'interfaccia Java interattiva, ma provare a scrivere interattivamente qualsiasi codice tipicamente statico sarebbe noioso, quindi non è così.

Nel mondo Java, la macchina virtuale ruba lo spettacolo perché esegue programmi scritti in un linguaggio che può essere effettivamente compilato in istruzioni macchina e il risultato è la velocità e l'efficienza delle risorse. Il bytecode Java può essere eseguito dalla macchina virtuale Java con prestazioni vicine a quelle dei programmi compilati, relativamente parlando. Ciò è dovuto alla presenza di informazioni primitive sul tipo di dati nel bytecode. La macchina virtuale Java colloca Java in una categoria a sé stante:

linguaggio interpretato staticamente tipicamente portatile

La prossima cosa più vicina è LLVM, ma LLVM opera a un livello diverso:

linguaggio assembly interpretato portatile

Il termine "bytecode" è usato sia in Java che in Python, ma non tutti i bytecode sono uguali. bytecode è solo il termine generico per le lingue intermedie utilizzato dai compilatori / interpreti. Perfino compilatori C come gcc usano un linguaggio intermedio (o diversi) per portare a termine il lavoro. Il bytecode Java contiene informazioni sui tipi di dati primitivi, mentre il bytecode Python no. A questo proposito, la macchina virtuale Python (e Bash, Perl, Ruby, ecc.) È veramente fondamentalmente più lenta della macchina virtuale Java, o meglio, ha semplicemente più lavoro da fare. È utile considerare quali informazioni sono contenute in diversi formati bytecode:

  • llvm: registri cpu
  • Java: tipi di dati primitivi
  • Python: tipi definiti dall'utente

Per disegnare un'analogia del mondo reale: LLVM funziona con gli atomi, la macchina virtuale Java funziona con le molecole e la macchina virtuale Python funziona con i materiali. Poiché alla fine tutto deve decomporsi in particelle subatomiche (operazioni di macchine reali), la macchina virtuale Python ha il compito più complesso.

Gli interpreti / compilatori di linguaggi tipicamente statici non hanno lo stesso bagaglio degli interpreti / compilatori di linguaggi tipicamente dinamici. I programmatori di linguaggi tipicamente statici devono occuparsi del gioco, per il quale il profitto è la prestazione. Tuttavia, proprio come tutte le funzioni non deterministiche sono segretamente deterministiche, così come lo sono tutte le lingue tipizzate dinamicamente in maniera segreta. Le differenze di prestazioni tra le due famiglie di lingue dovrebbero quindi livellarsi nel tempo in cui Python cambia nome in HAL 9000.

Le macchine virtuali di linguaggi dinamici come Python implementano alcune macchine logiche idealizzate e non corrispondono necessariamente molto da vicino a nessun hardware fisico reale. La macchina virtuale Java, al contrario, è più simile in termini di funzionalità a un classico compilatore C, tranne per il fatto che invece di emettere le istruzioni della macchina, esegue routine integrate. In Python, un numero intero è un oggetto Python con un gruppo di attributi e metodi associati. In Java, un int è un numero designato di bit, di solito 32. Non è davvero un confronto equo. Gli interi Python dovrebbero essere realmente confrontati con la classe Integer Java. Il tipo di dati primitivo "int" di Java non può essere paragonato a nulla nel linguaggio Python, perché il linguaggio Python manca semplicemente di questo livello di primitive, così come il bytecode Python.

Poiché le variabili Java sono tipizzate in modo esplicito, ci si può ragionevolmente aspettare che qualcosa come le prestazioni di Jython si trovino nello stesso campo di gioco di cPython . D'altra parte, una macchina virtuale Java implementata in Python è quasi garantita per essere più lenta del fango. E non aspettarti che Ruby, Perl, ecc. Andranno meglio. Non sono stati progettati per farlo. Sono stati progettati per lo "scripting", che è ciò che viene chiamato programmazione in un linguaggio dinamico.

Ogni operazione che si svolge in una macchina virtuale alla fine deve colpire l'hardware reale. Le macchine virtuali contengono routine precompilate che sono abbastanza generali da eseguire qualsiasi combinazione di operazioni logiche. Una macchina virtuale potrebbe non emettere nuove istruzioni per la macchina, ma certamente sta eseguendo le proprie routine più e più volte in sequenze arbitrariamente complesse. La macchina virtuale Java, la macchina virtuale Python e tutte le altre macchine virtuali per uso generale disponibili sono uguali nel senso che possono essere persuase a eseguire qualsiasi logica si possa immaginare, ma sono diverse in termini di attività che assumere e quali compiti lasciano al programmatore.

Psyco per Python non è una macchina virtuale Python completa, ma un compilatore just-in-time che dirotta la normale macchina virtuale Python in punti in cui pensa di poter compilare alcune righe di codice - principalmente loop dove pensa che il tipo primitivo di alcuni la variabile rimarrà costante anche se il valore cambia ad ogni iterazione. In tal caso, può rinunciare ad una incessante determinazione del tipo della normale macchina virtuale. Devi stare un po 'attento, però, per non estrarre il tipo da sotto i piedi di Psyco. Pysco, tuttavia, di solito sa tornare alla normale macchina virtuale se non è completamente sicuro che il tipo non cambierà.

La morale della storia è che le informazioni primitive sul tipo di dati sono davvero utili per un compilatore / macchina virtuale.

Infine, per mettere tutto in prospettiva, considera questo: un programma Python eseguito da un interprete / macchina virtuale Python implementato in Java in esecuzione su un interprete Java / macchina virtuale implementato in LLVM in esecuzione in una macchina virtuale qemu in esecuzione su un iPhone.

permalink


1
trying to write any statically-typed code interactively would be tedious. Se conosci OCaml e Haskell vedrai che non è vero poiché sono linguaggi tipicamente statici molto concisi.
Matthias Braun,

@MatthiasBraun Sono d'accordo sul fatto che quei linguaggi funzionali producono codice conciso, ma ciò non significa necessariamente che siano adatti alla modalità interattiva. Se OCaml e Haskell fossero stati digitati in modo dinamico come lisp, avrebbero funzionato meglio per la modalità interattiva presumo.
bombe

58

Probabilmente uno dei motivi della diversa terminologia è che normalmente si pensa di alimentare il codice sorgente raw interpretabile dall'interprete di Python e di non preoccuparsi del bytecode e tutto il resto.

In Java, è necessario compilare esplicitamente in bytecode e quindi eseguire solo il bytecode, non il codice sorgente sulla VM.

Anche se Python utilizza una macchina virtuale sotto le copertine, dal punto di vista dell'utente, è possibile ignorare questo dettaglio il più delle volte.


1
Sono d'accordo. Questa differenza nella terminologia dipende davvero dall'esperienza dell'utente finale (sviluppatore, cioè). Non ha nulla a che fare con le differenze tecniche reali, poiché la linea tecnica è così incredibilmente sfocata da essere quasi inesistente.
Cody Brocious,

1
+1: E - soprattutto - qual è il punto? Quale programma non puoi scrivere a causa di questa distinzione? Quale stackback trace ti sta confondendo? Quale libreria non sembra funzionare correttamente?
S. Lott

@ S.Lott Perché è sempre bello vincere discussioni con i colleghi. ;)
Qix - MONICA È STATA MISTREATA il

16

Interprete , traduce il codice sorgente in una rappresentazione intermedia (codice) efficiente ed esegue immediatamente questo.

Macchina virtuale , esegue esplicitamente il codice precompilato memorizzato creato da un compilatore che fa parte del sistema di interpretazione.

Una caratteristica molto importante di una macchina virtuale è che il software in esecuzione all'interno è limitato alle risorse fornite dalla macchina virtuale. Precisamente, non può uscire dal suo mondo virtuale. Pensa all'esecuzione sicura di codice remoto, Applet Java.

Nel caso di Python, se manteniamo i file Pyc , come menzionato nel commento di questo post, il meccanismo diventerebbe più simile a una VM, e questo bytecode verrà eseguito più velocemente - sarebbe comunque interpretato ma da una forma molto più amichevole per computer . Se consideriamo questo nel suo insieme, PVM è un ultimo passo di Python Interpreter.

La linea di fondo è, quando si fa riferimento a Python Interpreter, significa che lo stiamo riferendo nel suo insieme, e quando diciamo PVM, significa che stiamo solo parlando di una parte di Python Interpreter, un ambiente di runtime. Simile a quello di Java, ci riferiamo a diverse parti differenziali, JRE, JVM, JDK, ecc.

Per di più, Wikipedia: Interprete e macchina virtuale . Ancora un altro qui . Qui puoi trovare il Confronto di macchine virtuali applicative . Aiuta a comprendere la differenza tra compilatori, interpreti e VM.


12

Il termine interprete è un termine legacy che risale ai precedenti linguaggi di script di shell. Man mano che i "linguaggi di scripting" si sono evoluti in linguaggi completi e le piattaforme corrispondenti sono diventate più sofisticate e sandbox, la distinzione tra una macchina virtuale e un interprete (nel senso di Python) è molto piccola o inesistente.

L'interprete Python funziona ancora allo stesso modo di uno script di shell, nel senso che può essere eseguito senza un passo di compilazione separato. Oltre a ciò, le differenze tra l'interprete di Python (o Perl o Ruby) e la macchina virtuale di Java sono per lo più dettagli di implementazione. (Si potrebbe sostenere che Java è più completamente sandbox di Python, ma entrambi alla fine forniscono l'accesso all'architettura sottostante tramite un'interfaccia C nativa.)


1
ci sono shell Java che possono eseguire codice Java senza fasi di compilazione separate (visibili all'utente).
Lie Ryan,

1
dammi il nome: D
Maciej Nowicki,

11

Per fornire una risposta profonda alla domanda " Perché Java Virtual Machine, ma interprete Python? " Proviamo a tornare al campo della teoria della compilazione per quanto riguarda il punto di partenza della discussione.

Il tipico processo di compilazione del programma include i passaggi seguenti:

  1. Analisi lessicale . Suddivide il testo del programma in "parole" significative chiamate token (come parte del processo vengono rimossi tutti i commenti, gli spazi, le nuove righe, ecc., Poiché non influiscono sul comportamento del programma). Il risultato è un flusso ordinato di token.
  2. L'analisi della sintassi . Costruisce il cosiddetto Abstract Syntax Tree (AST) dal flusso di token. AST stabilisce relazioni tra i token e, di conseguenza, definisce un ordine di valutazione del programma.
  3. Analisi semantica . Verifica la correttezza semantica dell'AST utilizzando informazioni sui tipi e un insieme di regole semantiche del linguaggio di programmazione. (Ad esempio, a = b + cè un'istruzione corretta dal punto di vista della sintassi, ma completamente errata dal punto di vista semantico se è astata dichiarata come oggetto costante)
  4. Generazione di codice intermedio . Serializza AST nel flusso ordinato in modo lineare di operazioni "primitive" indipendenti dalla macchina. In effetti, il generatore di codice attraversa AST e registra l'ordine delle fasi di valutazione. Di conseguenza, dalla rappresentazione ad albero del programma, otteniamo una rappresentazione molto simile a una lista in cui l'ordine di valutazione del programma viene preservato.
  5. Generazione di codice macchina . Il programma sotto forma di bytecode "primitivo" indipendente dalla macchina viene tradotto in codice macchina di particolare architettura di processore.

Ok. Consente ora di definire i termini.

L'interprete , nel significato classico di quella parola, presuppone l'esecuzione basata sulla valutazione del programma basata su AST prodotta direttamente dal testo del programma . In tal caso, un programma viene distribuito sotto forma di codice sorgente e l'interprete viene alimentato dal testo del programma, spesso in modo dinamico (istruzione per istruzione o riga per riga). Per ogni istruzione di input, l'interprete crea il suo AST e lo valuta immediatamente cambiando lo "stato" del programma. Questo è un comportamento tipico dimostrato dai linguaggi di scripting. Consideriamo ad esempio Bash, Windows CMD, ecc. Concettualmente, anche Python prende questa strada.

Se sostituiamo il passaggio di esecuzione basato su AST sulla generazione del passaggio di codice binario intermedio indipendente dalla macchina nell'interprete, divideremo l'intero processo di esecuzione del programma in due fasi distinte: compilazione ed esecuzione. In quel caso quello che prima era un interprete diventerà un compilatore bytecode, che trasformerà il programma dalla forma del testo in una forma binaria . Quindi il programma viene distribuito in quella forma binaria, ma non sotto forma di codice sorgente. Sul computer dell'utente, quel bytecode viene inserito in una nuova entità: la macchina virtuale , che in realtà interpreta quel bytecode. Per questo motivo, le macchine virtuali sono anche chiamate interprete bytecode . Ma attenzione qui! Un interprete classico è ainterprete di testo , ma una macchina virtuale è un interprete binario ! Questo è un approccio adottato da Java e C #.

Infine, se aggiungiamo la generazione del codice macchina al compilatore bytecode, otteniamo di conseguenza quello che chiamiamo un compilatore classico . Un compilatore classico converte il codice sorgente del programma nel codice macchina di un particolare processore. Tale codice macchina può quindi essere eseguito direttamente sul processore di destinazione senza alcuna mediazione aggiuntiva (senza alcun tipo di interprete né interprete di testo né interprete binario).

Ora torniamo alla domanda originale e consideriamo Java vs Python.

Java è stato inizialmente progettato per avere il minor numero possibile di dipendenze di implementazione. Il suo design si basa sul principio "scrivi una volta, corri ovunque" (WORA). Per implementarlo, Java è stato inizialmente progettato come un linguaggio di programmazione che si compila in bytecode binario indipendente dalla macchina , che quindi può essere eseguito su tutte le piattaforme che supportano Java senza la necessità della sua ricompilazione. Puoi pensare a Java come al C ++ basato su WORA . In realtà, Java è più vicino al C ++ che ai linguaggi di scripting come Python . Ma a differenza di C ++ , Javaè stato progettato per essere compilato in bytecode binario che viene quindi eseguito nell'ambiente della macchina virtuale , mentre C ++ è stato progettato per essere compilato in codice macchina e quindi eseguito direttamente dal processore di destinazione.

Python inizialmente è stato progettato come una sorta di linguaggio di programmazione di scripting che interpreta gli script (programmi sotto forma di testo scritto in conformità con le regole del linguaggio di programmazione). Per questo motivo, Python ha inizialmente supportato un'interpretazione dinamica di comandi o istruzioni a riga singola, come fanno Bash o Windows CMD. Per lo stesso motivo, le implementazioni iniziali di Python non avevano alcun tipo di compilatore bytecode e macchine virtuali per l'esecuzione di tale bytecode all'interno, ma fin dall'inizio Python aveva richiesto un interprete in grado di comprendere e valutare il testo del programma Python .

Per questo motivo , storicamente, gli sviluppatori Java tendevano a parlare di Java Virtual Machine (perché inizialmente Java è arrivato come pacchetto del compilatore bytecode Java e dell'interprete bytecode - JVM ), e gli sviluppatori Python tendevano a parlare dell'interprete Python (perché inizialmente Python ha non una macchina virtuale ed era una sorta di interprete di testo classico che esegue direttamente il testo del programma senza alcun tipo di compilazione o trasformazione in qualsiasi forma di codice binario).

Attualmente, Python ha anche la macchina virtuale sotto il cofano e può compilare e interpretare il bytecode Python. E questo fatto fa un ulteriore investimento nella confusione " Perché Java Virtual Machine, ma interprete Python?e che i programmi dimostreranno esattamente lo stesso comportamento e produrranno ugualmente lo stesso output dall'input uguale. L'unica differenza osservabile sarà la velocità di esecuzione del programma e la quantità di memoria consumata dall'interprete. Pertanto, la macchina virtuale in Python non è una parte inevitabile della progettazione del linguaggio, ma solo un'estensione opzionale del principale interprete Python.

Java può essere considerato in modo simile. Java under the hood ha un compilatore JIT e può compilare selettivamente i metodi della classe Java nel codice macchina della piattaforma di destinazione e quindi eseguirlo direttamente. Ma! Java utilizza ancora l'interpretazione bytecode come metodo principale per l'esecuzione del programma Java. Come le implementazioni di Python che sfruttano le macchine virtuali sotto il cofano esclusivamente come tecnica di ottimizzazione, le macchine virtuali Java utilizzano compilatori Just-In-Time esclusivamente a fini di ottimizzazione. Allo stesso modo, proprio per il fatto che l'esecuzione diretta del codice macchina è almeno dieci volte più veloce dell'interpretazione del bytecode Java. E come nel caso di Python, la presenza del compilatore JIT sotto il cofano di JVM è assolutamente trasparente sia per i progettisti del linguaggio Java che per gli sviluppatori di programmi Java. Lo stesso linguaggio di programmazione Java può essere implementato da JVM con e senza compilatore JIT. E allo stesso modo, gli stessi programmi possono essere eseguiti in JVM con e senza JIT all'interno, e gli stessi programmi dimostreranno esattamente lo stesso comportamento e produrranno ugualmente lo stesso output dall'input uguale su entrambi JVM (con e senza JIT). E come nel caso di Python, l'unica differenza osservabile tra loro, sarà nella velocità di esecuzione e nella quantità di memoria consumata da JVM. E infine, come nel caso di Python, anche JIT in Java non è una parte inevitabile della progettazione del linguaggio, ma solo un'estensione opzionale delle principali implementazioni JVM. e gli stessi programmi dimostreranno esattamente lo stesso comportamento e produrranno ugualmente lo stesso output dall'input uguale su entrambe le JVM (con e senza JIT). E come nel caso di Python, l'unica differenza osservabile tra loro, sarà nella velocità di esecuzione e nella quantità di memoria consumata da JVM. E infine, come nel caso di Python, anche JIT in Java non è una parte inevitabile della progettazione del linguaggio, ma solo un'estensione opzionale delle principali implementazioni JVM. e gli stessi programmi dimostreranno esattamente lo stesso comportamento e produrranno ugualmente lo stesso output dall'input uguale su entrambe le JVM (con e senza JIT). E come nel caso di Python, l'unica differenza osservabile tra loro, sarà nella velocità di esecuzione e nella quantità di memoria consumata da JVM. E infine, come nel caso di Python, anche JIT in Java non è una parte inevitabile della progettazione del linguaggio, ma solo un'estensione opzionale delle principali implementazioni JVM.

Dal punto di vista della progettazione e dell'implementazione delle macchine virtuali di Java e Python, differiscono in modo significativo, mentre (attenzione!) Rimangono entrambe le macchine virtuali. JVM è un esempio di macchina virtuale di basso livello con semplici operazioni di base e costi di invio delle istruzioni elevati. Python a sua volta è una macchina virtuale di alto livello, per la quale le istruzioni dimostrano un comportamento complesso e il costo di invio delle istruzioni non è così significativo. Java funziona con un livello di astrazione molto basso. JVM opera su un piccolo insieme ben definito di tipi primitivi e ha una corrispondenza molto stretta (in genere uno a uno) tra le istruzioni bytecode e le istruzioni del codice macchina nativo. Al contrario, la macchina virtuale Python opera ad alto livello di astrazione, opera con tipi di dati complessi (oggetti) e supporta il polimorfismo ad hoc, mentre le istruzioni bytecode espongono comportamenti complessi, che possono essere rappresentati da una serie di istruzioni multiple di codice macchina nativo. Ad esempio, Python supporta matematica con intervallo illimitato. Pertanto, Python VM è costretta a sfruttare aritmetiche lunghe per numeri interi potenzialmente grandi per i quali il risultato dell'operazione può traboccare la parola macchina. Quindi, un'istruzione bytecode per l'aritmetica in Python può esporre nella chiamata di funzione all'interno di Python VM, mentre nelle operazioni aritmetiche JVM si espone in un'operazione semplice espressa da una o poche istruzioni native della macchina. Pertanto, Python VM è costretta a sfruttare aritmetiche lunghe per numeri interi potenzialmente grandi per i quali il risultato dell'operazione può traboccare la parola macchina. Quindi, un'istruzione bytecode per l'aritmetica in Python può esporre nella chiamata di funzione all'interno di Python VM, mentre nelle operazioni aritmetiche JVM si espone in un'operazione semplice espressa da una o poche istruzioni native della macchina. Pertanto, Python VM è costretta a sfruttare aritmetiche lunghe per numeri interi potenzialmente grandi per i quali il risultato dell'operazione può traboccare la parola macchina. Quindi, un'istruzione bytecode per l'aritmetica in Python può esporre nella chiamata di funzione all'interno di Python VM, mentre nelle operazioni aritmetiche JVM si espone in un'operazione semplice espressa da una o poche istruzioni native della macchina.

Di conseguenza, possiamo trarre le prossime conclusioni. Java Virtual Machine ma l'interprete Python è perché:

  1. Il termine macchina virtuale presuppone l'interpretazione binaria del bytecode, mentre il termine interprete assume l'interpretazione del testo del programma.
  2. Storicamente, Java è stato progettato e implementato per l'interpretazione binaria di bytecode e Python inizialmente è stato progettato e implementato per l'interpretazione del testo del programma. Pertanto, il termine "Java Virtual Machine" è storico e ben consolidato nella comunità Java. Allo stesso modo, il termine "interprete Python" è storico e ben consolidato nella comunità Python. I popoli tendono a prolungare la tradizione e usano gli stessi termini usati molto tempo prima.
  3. Infine, attualmente, per Java, l'interpretazione binaria del bytecode è un modo primario di esecuzione dei programmi, mentre la compilazione JIT è solo un'ottimizzazione opzionale e trasparente. E per Python, attualmente, l'interpretazione del testo del programma è un modo primario di esecuzione dei programmi Python, mentre la compilazione in bytecode VM Python è solo un'ottimizzazione opzionale e trasparente.

Pertanto, sia Java che Python hanno macchine virtuali, sono interpreti binari bytecode, che possono creare confusione come " Perché Java Virtual Machine, ma interprete Python?". Il punto chiave qui è che per Python, una macchina virtuale non è un mezzo primario o necessario per l'esecuzione del programma; è solo un'estensione opzionale dell'interprete di testo classico. D'altra parte, una macchina virtuale è un nucleo e inevitabile parte dell'ecosistema di esecuzione del programma Java La scelta di digitare statica o dinamica per la progettazione del linguaggio di programmazione influisce principalmente solo sul livello di astrazione della macchina virtuale, ma non determina se è necessaria una macchina virtuale. Le lingue che utilizzano entrambi i sistemi di battitura possono essere progettate per essere compilate , interpretato o eseguito all'interno dell'ambiente della macchina virtuale, a seconda del modello di esecuzione desiderato.


2
Questa dovrebbe essere scelta come risposta ufficiale IMHO.
Ravikanth Andhavarapu,

La risposta ufficiale dovrebbe essere YES poiché "sia Java che Python hanno macchine virtuali sono interpreti binari bytecode". Periodo.
stuartw

10

Non c'è alcuna vera differenza tra loro, le persone seguono semplicemente le convenzioni che i creatori hanno scelto.


3
Ti lancerò un osso qui poiché penso che questa sia probabilmente la vera risposta e tu abbia votato per mancanza di bit.
vikingben,

3

Non dimenticare che Python ha compilatori JIT disponibili per x86, confondendo ulteriormente il problema. (Vedi psyco).

Un'interpretazione più rigorosa di un "linguaggio interpretato" diventa utile solo quando si discute di problemi di prestazioni della VM, ad esempio, rispetto a Python, Ruby è stato (è?) Considerato più lento perché è un linguaggio interpretato, a differenza di Python - in altri parole, il contesto è tutto.


1
È sbagliato. Innanzitutto, non esiste un "linguaggio interpretato". Se un'implementazione utilizza un compilatore o un interprete non è una caratteristica della lingua ma dell'implementazione. In secondo luogo, delle 13 o più implementazioni di Ruby, esattamente 1 è un interprete, tutti gli altri hanno compilatori.
Jörg W Mittag,

2
Terzo, Ruby non è lento. Nessuna lingua è lenta, perché la velocità non è una caratteristica della lingua, ma l'implementazione della lingua. Delle 13 o più implementazioni di Ruby, alcune sono più lente di alcune delle 7 implementazioni di Python, altre sono più veloci.
Jörg W Mittag,

Penso che stia confrontando le implementazioni standard qui Jörg. CPython e Ruby (penso che l'implementazione ufficiale si chiami solo Ruby).
James McMahon,

Mentre Arafangion potrebbe riferirsi alle implementazioni "standard", avrebbe dovuto dirlo. Sono un Pythonista ma odio qualsiasi affermazione del modulo "Il linguaggio X è lento", dal momento che sono d'accordo con Jörg sulla questione delle implementazioni.
martedì

1
Questo è esattamente il motivo per cui ho detto "era (è?)", E in particolare il termine "più lento". Da nessuna parte ho detto che Ruby è di per sé lento.
Arafangion,

2

Python può interpretare il codice senza compilarlo in bytecode. Java non può .

Python è un linguaggio interpretato, al contrario di un linguaggio compilato, sebbene la distinzione possa essere sfocata a causa della presenza del compilatore bytecode. Ciò significa che i file di origine possono essere eseguiti direttamente senza creare esplicitamente un eseguibile che viene quindi eseguito.

(dalla documentazione).

In Java, ogni singolo file deve essere compilato in un .classfile, che viene quindi eseguito sulla JVM. Al contrario, Python viene importato dallo script principale per velocizzare gli usi successivi di tali file.

Tuttavia, nel caso tipico, la maggior parte del codice python (almeno, CPython) viene eseguito in una macchina stack emulata, che ha istruzioni quasi identiche a quelle della JVM, quindi non c'è grande differenza.

Il vero motivo della distinzione è tuttavia perché, fin dall'inizio, Java si è marchiato come "bytecode portatile, eseguibile" e Python si è marchiato come linguaggio interpretato dinamico con un REPL. Stick di nomi!


0

Prima di tutto dovresti capire che la programmazione o l'informatica in generale non sono matematica e non abbiamo definizioni rigorose per la maggior parte dei termini che usiamo spesso.

ora alla tua domanda:

cos'è un interprete (in informatica)

Traduce il codice sorgente per l'unità eseguibile più piccola e quindi esegue quell'unità.

cos'è una macchina virtuale

nel caso di JVM la macchina virtuale è un software che contiene un interprete, caricatori di classi, garbage collector, thread scheduler, compilatore JIT e molte altre cose.

come puoi vedere, l'interprete è una parte o JVM e l'intera JVM non può essere chiamata interprete perché contiene molti altri componenti.

perché usare la parola "interprete" quando si parla di pitone

con java la parte della compilation è esplicita. python d'altra parte non è esplicito come java sul suo processo di compilazione e interpretazione, dal punto di vista dell'interpretazione dell'utente finale è l'unico meccanismo utilizzato per eseguire i programmi python


0

No, entrambi non interpretano il codice byte.

Python interpreta il bytecode solo se si esegue con pypy. Altrimenti viene compilato in C e interpretato a quel livello.

Java viene compilato in bytecode.


Puoi dare qualche risorsa alla tua risposta?
Isuru Dilshan,


Questo è ciò che non va in Stack Overflow. Qualcuno ha una forma incazzata perché viene chiamato ed esprime con voti negativi.
Michael Tamillow,

0

Penso che le linee tra i due siano sfocate, le persone discutono principalmente sul significato della parola "interprete" e su quanto la lingua si avvicini ad ogni lato dello spettro "interprete ... compilatore". Nessuno ne fa il 100% comunque. Penso che sia facile scrivere un'implementazione Java o Python di qualsiasi valore dello spettro.

Attualmente sia Java che Python hanno macchine virtuali e bytecode, sebbene uno operi per dimensioni di valori concreti (come numeri interi a 32 bit) mentre altri devono determinare le dimensioni per ogni chiamata, che a mio avviso non definisce il confine tra i termini.

L'argomento secondo cui Python non ha definito ufficialmente il bytecode ed esiste solo in memoria non mi convince, solo perché sto progettando di sviluppare dispositivi che riconoscano solo il bytecode Python e la parte della compilazione verrà eseguita nel browser JS machine.

Le prestazioni riguardano solo l'implementazione concreta. Non abbiamo bisogno di conoscere le dimensioni dell'oggetto per poter lavorare con esso e infine, nella maggior parte dei casi, lavoriamo con strutture, non con tipi di base. È possibile ottimizzare Python VM nel modo in cui eliminerà la necessità di creare nuovi oggetti ogni volta durante il calcolo dell'espressione, riutilizzando quello esistente. Una volta fatto, non vi è alcuna differenza di prestazioni globali tra il calcolo della somma di due numeri interi, che è dove splende Java.

Non c'è alcuna differenza killer tra i due, solo alcune sfumature di implementazione e mancanza di ottimizzazione che sono irrilevanti per l'utente finale, forse nel punto in cui inizia a notare ritardi nelle prestazioni, ma di nuovo si tratta di implementazione e non di problemi di architettura.


0

per i post che menzionano che python non ha bisogno di generare codice byte, non sono sicuro che sia vero. sembra che tutti i callable in Python debbano avere un .__code__.co_codeattributo che contiene il codice byte. Non vedo una ragione significativa per chiamare Python "non compilato" solo perché gli artefatti compilati potrebbero non essere salvati; e spesso non vengono salvati dalla progettazione in Python, ad esempio tutta la comprensione compila un nuovo bytecode per il suo input, questo è il motivo per cui l'ambito della variabile di comprensione non è coerente tra compile(mode='exec, ...)e compilare compile(mode='single', ...)come tra l'esecuzione di uno script Python e l'uso di pdb

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.