Perché Python non ha bisogno di un compilatore?

28

Mi sto chiedendo (ora che ho iniziato con C ++ che ha bisogno di un compilatore) perché Python non ha bisogno di un compilatore?

Ho appena inserito il codice, salvato come exec ed eseguito. In C ++ devo creare build e tutte quelle altre cose divertenti.

    
posta Billjk 26.02.2012 - 01:57
fonte

5 risposte

66

Python ha un compilatore! Semplicemente non te ne accorgi perché funziona automaticamente. Puoi dire che è lì, però: guarda .pyc (o .pyo se hai attivato l'ottimizzatore) i file che vengono generati per i moduli che tu import .

Inoltre, non si compila con il codice della macchina nativa. Invece, compila un codice byte che viene utilizzato da una macchina virtuale. La macchina virtuale è essa stessa un programma compilato. Questo è molto simile a come funziona Java; così simile, infatti, che esiste una variante Python ( Jython ) che invece compila il codice byte della Java Virtual Machine! C'è anche IronPython , che viene compilato con il CLR di Microsoft (usato da .NET). (Il normale compilatore di codice byte Python è talvolta chiamato CPython per disambigerlo da queste alternative.)

C ++ deve esporre il suo processo di compilazione perché il linguaggio stesso è incompleto; non specifica tutto ciò che il linker deve sapere per creare il tuo programma, né può specificare le opzioni di compilazione in modo portabile (alcuni compilatori ti permettono di usare #pragma , ma non è standard). Quindi devi fare il resto del lavoro con makefile e possibilmente l'inferno automatico (autoconf / automake / libtool). Questo è davvero solo un retaggio da come C l'ha fatto. E C l'ha fatto in questo modo perché rendeva il compilatore semplice, il che è uno dei motivi principali per cui è così popolare (chiunque potrebbe sfornare un semplice compilatore C negli anni '80).

Alcune cose che possono influenzare l'operazione del compilatore o del linker ma non sono specificate nella sintassi di C o C ++:

  • risoluzione delle dipendenze
  • requisiti della libreria esterna (incluso l'ordine di dipendenza)
  • livello di ottimizzazione
  • impostazioni di avviso
  • versione della specifica del linguaggio
  • mappature del linker (che sezione va dove nel programma finale)
  • architettura di destinazione

Alcuni di questi possono essere rilevati, ma non possono essere specificati; per esempio. Sono in grado di rilevare quale C ++ è in uso con __cplusplus , ma non posso specificare che C ++ 98 sia quello utilizzato per il mio codice all'interno del codice stesso; Devo passarlo come un flag al compilatore nel Makefile, o creare un'impostazione in una finestra di dialogo.

Sebbene si possa pensare che esista un sistema di "risoluzione delle dipendenze" nel compilatore, generando automaticamente dei record di dipendenza, questi record indicano solo i file di intestazione utilizzati da un dato file sorgente. Non possono indicare quali moduli aggiuntivi del codice sorgente sono necessari per collegarsi a un programma eseguibile, perché non esiste un modo standard in C o C ++ per indicare che un determinato file di intestazione è la definizione di interfaccia per un altro modulo di codice sorgente anziché solo un gruppo di linee che vuoi mostrare in più punti in modo da non ripeterti. Ci sono tradizioni nelle convenzioni sui nomi dei file, ma queste non sono conosciute o applicate dal compilatore e dal linker.

Molti di questi possono essere impostati usando #pragma , ma questo non è standard, e stavo parlando dello standard. Tutte queste cose potrebbero essere specificate da uno standard, ma non sono state nell'interesse della retrocompatibilità. La saggezza prevalente è che i makefile e gli IDE non sono danneggiati, quindi non risolverli.

Python gestisce tutto questo nella lingua. Ad esempio, import specifica una dipendenza del modulo esplicita, implica la struttura di dipendenza e i moduli non sono suddivisi in file di intestazione e di origine (cioè interfaccia e implementazione).

    
risposta data 26.02.2012 - 02:16
fonte
5

Python è un linguaggio interpretato. Ciò significa che sul tuo computer è presente un software che legge il codice Python e invia le "istruzioni" alla macchina. L' articolo di Wikipedia sulle lingue interpretate potrebbe essere di interesse.

Quando una lingua come C ++ (un linguaggio compilato) è compilata, significa che è convertita in codice macchina per essere letta direttamente dall'hardware quando viene eseguita. L' articolo di Wikipedia sulle lingue compilate potrebbe fornire un contrasto interessante.

    
risposta data 26.02.2012 - 02:04
fonte
4

Non tutti i linguaggi compilati hanno un ciclo di modifica edit-compile-link-in-face.

Quello che stai incontrando è una funzionalità / limitazione di C ++ (o almeno implementazioni C ++).

Per fare qualsiasi cosa, è necessario memorizzare il codice in file e creare un'immagine monolitica tramite un processo chiamato collegamento.

In particolare, è questo processo di collegamento monolitico che viene scambiato per la distinzione tra compilazione e interpretazione.

Alcune lingue fanno tutte queste cose molto più dinamicamente, eliminando la maldestra fase di collegamento monolitico, non eliminando la compilazione sul codice macchina. L'origine è ancora compilata in file oggetto, ma questi vengono caricati in un'immagine runtime, anziché essere collegati a un eseguibile monolitico.

Dici "ricarica questo modulo", carica la sorgente e la interpreta, o la compila, a seconda di un interruttore di modalità.

La programmazione del kernel Linux ha un po 'di questo sapore anche se stai lavorando in C. Puoi ricompilare un modulo e caricarlo e scaricarlo. Certo, sei ancora consapevole del fatto che stai producendo qualcosa di eseguibile, ed è gestito da un sistema di build complesso, con ancora alcuni passaggi manuali. Ma il fatto è che alla fine puoi scaricare e ricaricare solo quel piccolo modulo e non dover riavviare l'intero kernel.

Alcune lingue hanno una modularizzazione ancora più fine di questa e la costruzione e il caricamento avvengono dall'interno del loro tempo di esecuzione, quindi è più semplice.

    
risposta data 05.03.2012 - 07:30
fonte
2

che diversivo dalla domanda iniziale ... Un punto non menzionato è che la fonte di un programma python è ciò che usi e distribuisci, dal punto di vista dell'utente è il programma. Tendiamo a semplificare le cose in categorie che non sono ben definite.

I programmi compilati sono generalmente considerati come file autonomi di codice macchina. (Presumibilmente spesso contiene collegamenti a librerie di collegamenti dinamici associati a sistemi operativi specifici). Detto questo ... ci sono variazioni nella maggior parte dei linguaggi di programmazione che potrebbero essere descritti come compilati o interpretati.

Python non ha bisogno di un compilatore perché si affida a un'applicazione (chiamata interprete) che compila ed esegue il codice senza memorizzare il codice macchina creato in un modulo facilmente accessibile o distribuito.

    
risposta data 25.09.2013 - 23:39
fonte
1

Tutti i linguaggi di programmazione richiedono la traduzione da concetti umani in un codice macchina di destinazione. Anche il linguaggio assembly deve essere tradotto in codice macchina. Questa traduzione di solito avviene nelle seguenti fasi:

Fase 1: analisi e traduzione (analisi) in un codice intermedio. Fase 2: traduzione del codice intermedio nel codice macchina di destinazione con segnaposti per riferimenti esterni. Fase 3: risoluzione dei riferimenti esterni e della confezione in un programma eseguibile della macchina.

Questa traduzione viene spesso definita come pre-compilazione e "Just in time" (JIT) o compilazione in fase di esecuzione.

Lingue come C, C ++, COBOL, Fortran, Pascal (non tutte) e Assembly sono lingue precompilate che possono essere eseguite direttamente dal sistema operante senza bisogno di un interprete.

Lingue come Java, BASIC, C # e Python sono interpretate. Tutti usano il codice intermedio creato nella Fase 1, ma a volte differiscono nel modo in cui lo traducono in codice macchina. Le forme più semplici usano quel codice intermedio per eseguire routine di codice macchina che eseguono il lavoro previsto. Altri compilano il codice intermedio fino al codice macchina e eseguono il fixing delle dipendenze esterne durante il runtime. Una volta compilato può essere immediatamente eseguito. Inoltre, il codice macchina è memorizzato in una cache di codice macchina riutilizzabile precedentemente compilato che può essere riutilizzato in seguito se la funzione è necessaria in seguito. Se una funzione è già stata memorizzata nella cache, l'interprete non ha bisogno di compilarlo di nuovo.

La maggior parte dei linguaggi di alto livello moderni rientrano nella categoria interpretata (con JIT). Sono soprattutto le lingue più vecchie come C & C ++ precompilato.

    
risposta data 07.07.2017 - 22:58
fonte

Leggi altre domande sui tag