Dlaczego Python potrzebuje zarówno kompilatora, jak i interpretera?

9

Rozumiem fakt, że Java potrzebuje zarówno kompilatora, jak i interpretera. Kompiluje kod źródłowy do kodu bajtowego, a następnie maszyna wirtualna (w systemie Windows, Linux, Android itp.) Tłumaczy ten kod bajtowy na kod maszynowy dla bieżącej architektury.

Ale dlaczego Python potrzebuje zarówno kompilatora, jak i interpretera? Ponieważ Python nie jest niezależny od platformy, dlaczego nie skorzystać z interpretacji? O ile mi wiadomo, nie można uruchomić programu Python (skompilowanego do kodu bajtowego) na żadnym komputerze z systemem Windows lub Linux bez modyfikacji. A może się mylę?

aris
źródło
Możesz się mylić Jeśli użyjesz Lua zamiast Pythona, pomylisz się.
Basile Starynkevitch,

Odpowiedzi:

13

O ile mi wiadomo, nie można uruchomić programu Python (skompilowanego do kodu bajtowego) na każdym komputerze, na przykład w systemie Windows lub Linux bez modyfikacji.

Jesteś w błędzie Kod bajtowy python jest wieloplatformowy. Zobacz Czy kod bajtowy Pythona jest zależny od wersji? Czy to zależy od platformy? na przepełnienie stosu. Jednak nie jest kompatybilny między wersjami. Python 2.6 nie może uruchamiać plików Python 2.5. Chociaż jest to platforma wieloplatformowa, nie jest ogólnie przydatna jako format dystrybucji.

Ale dlaczego Python potrzebuje zarówno kompilatora, jak i interpretera?

Prędkość. Ścisła interpretacja jest powolna. Praktycznie każdy „zinterpretowany” język faktycznie kompiluje kod źródłowy w jakąś wewnętrzną reprezentację, aby nie musiał wielokrotnie parsować kodu. W przypadku Pythona zapisuje tę wewnętrzną reprezentację na dysku, aby mógł pominąć proces analizowania / kompilowania następnym razem, gdy będzie potrzebował kodu.

Winston Ewert
źródło
7

Rozumiem fakt, że Java potrzebuje zarówno kompilatora, jak i interpretera.

Tak nie jest. W specyfikacji języka Java nie ma nic, co mówi, że Java musi mieć kompilator. W specyfikacji języka Java nie ma też nic, co mówi, że Java musi mieć tłumacza.

Niezależnie od tego, czy użyć interpretera, kompilatora, czy też ich kombinacji, całkowicie zależy to od implementatora.

W rzeczywistości nie implementacje Javy, która od razu do kompilacji kodu maszynowego, np GNU Compiler for Java gcj. Mówiąc technicznie, kompilator Java Oracle OpenJDK również kompiluje się do kodu maszynowego, w szczególności kodu bajtowego JVM. Teraz możesz powiedzieć, poczekaj chwilę, to nie jest kod maszynowy! Istnieją jednak interpretery oprogramowania dla kodu maszynowego x86 i istnieją sprzętowe procesory, które mogą wykonywać kod bajtowy JVM, więc co sprawia, że ​​jeden jest „natywny”, a drugi nie?

Należy pamiętać, że kod bajtu JVM znajduje się poza specyfikacją języka Java, podobnie jak kod maszynowy x86.

a następnie maszyna wirtualna (w systemie Windows, Linux, Android itp.) tłumaczy ten kod bajtowy na kod maszynowy dla bieżącej architektury.

Ponownie, to zależy wyłącznie od implementatora.

Oryginalna Sun JVM nigdy nie tłumaczyła, zawsze interpretowała. Obecny JVM Oracle OpenJDK interpretuje i tylko te części, które są często wykonywane, są kompilowane. Maszyna wirtualna Maxine Research zawsze kompiluje JIT. Implementacja Excelsior.JET kompiluje się raz, z wyprzedzeniem. JVM IKVM.NET kompiluje się do kodu bajtowego CIL. Android Runtime kompiluje się z wyprzedzeniem, raz podczas instalacji. (Ponadto środowisko wykonawcze Androida nie rozumie kodu bajtowego JVM, używa kodu bajtowego Dalvik, który jest zupełnie innym językiem.)

Ale dlaczego Python potrzebuje zarówno kompilatora, jak i interpretera?

Znowu tak nie jest. W specyfikacji języka Python nie ma nic, co mówi, że Python musi mieć kompilator. W Specyfikacji języka Python nie ma też nic, co mówi, że Python nie powinien mieć tłumacza.

Zauważ, że w rzeczywistości Python nigdy nie jest interpretowany. Wszystkie istniejące implementacje języka Python zawsze kompilują język Python w innym języku. Ten język może z kolei zostać zinterpretowany, ale ten język jest inny niż Python. Python nie jest interpretowany.

dlaczego nie skorzystać z interpretacji?

Ponieważ Python nie jest zaprojektowany do łatwej interpretacji przez maszyny. Został zaprojektowany z myślą o łatwej interpretacji przez ludzi. OTOH, kod bajtowy CPython, został zaprojektowany w taki sposób, aby mógł być łatwo interpretowany przez maszyny. Dlatego sensowne jest pisanie kodu w języku przeznaczonym dla ludzi i interpretowanie w języku przeznaczonym dla maszyn, a aby przejść od jednego do drugiego, trzeba skompilować.

O ile mi wiadomo, nie można uruchomić programu Python (skompilowanego do kodu bajtowego) na żadnym komputerze z systemem Windows lub Linux bez modyfikacji.

Tak, możesz. CPython VM jest dostępny zarówno dla systemu Windows, jak i Linux, podobnie jak PyPy, Jython i IronPython.


Języki nie muszą być kompilowane ani interpretowane. Języki po prostu . W rzeczywistości, język może doskonale istnieć bez żadnego interpreter lub kompilator! Na przykład Konrad Zuse's Plankalkül, który zaprojektował w latach 30. XX wieku, nigdy nie został wdrożony za życia. Nadal można w nim pisać programy, można je analizować, uzasadniać, udowadniać ich właściwości… po prostu nie można ich uruchomić. (Cóż, nawet to jest złe: możesz oczywiście uruchomić je w głowie lub za pomocą pióra i papieru.)

Teraz każda konkretna implementacja języka może korzystać z kompilatora (lub nawet wielu kompilatorów), tłumacza lub dowolnej kombinacji. Ale to cecha implementacji , a nie języka. Każdy język można zaimplementować za pomocą kompilatora, a każdy język można zaimplementować za pomocą tłumacza.

Należy jednak pamiętać, że nie można uruchomić programu bez interpretera. Kompilator po prostu tłumaczy program z jednego języka na inny. Ale to jest to. Teraz masz ten sam program, tylko w innym języku. Jedyny sposób, aby rzeczywiście uzyskać wynik programu jest interpretować go. Czasami język ten jest niezwykle prostym językiem maszynowym binarnym, a interpreter jest tak naprawdę zakodowany w silikonie (i nazywamy go „CPU”), ale nadal jest to interpretacja.

Być może zainteresuje Cię moja odpowiedź, która wyjaśnia różnice i różne sposoby łączenia interpreterów, kompilatorów JIT i kompilatorów AOT, a także tę odpowiedź dotyczącą różnic między kompilatorem AOT a kompilatorem JIT .

Jörg W Mittag
źródło
3
Smutne są odpowiedzi, które spędzają większość czasu na byciu pedantycznymi zamiast odpowiedzi na pytanie.
Winston Ewert,
3

To prawda, że ​​kod bajtowy nie jest odpowiedni jako format dystrybucji, ale to nie znaczy, że jest bezużyteczny. Oprócz poprawy czasu uruchamiania na danym komputerze, po pierwszym uruchomieniu interpretacja kodu bajtowego jest również znacznie prostsza niż interpretacja AST lub, na wszelki wypadek, interpretacja linia po linii.

Kod bajtowy to reprezentacja kodu na niższym poziomie, bardziej regularna, bardziej zwarta (zarówno semantycznie, jak i pod względem układu pamięci). Kolejność operacji jest już określona, ​​nazwy zmiennych lokalnych zostały rozwiązane w prostszej formie (indeksy całkowite). Żadnej skomplikowanej składni do naśladowania, tylko jedna prosta instrukcja po drugiej. Ponadto potrzebny jest mniejszy stan: do interpretacji wiersz po linii zasadniczo wystarczy utrzymać cały parser, a interpreter AST wysadza stos wywołań z przechodzeniem przez drzewo, podczas gdy interpreter kodu bajtowego potrzebuje tylko małego stosu dla wartości tymczasowych i miejscowi.

Te i inne czynniki powodują, że tłumacze kodu bajtowego są znacznie szybsi niż inni tłumacze.


źródło