Z mojego zrozumienia:
Interpretowany język jest prowadzony język wysokiego poziomu i wykonywane przez tłumacza (program, który konwertuje język wysokiego poziomu do kodu maszynowego, a następnie wykonanie) w podróży; przetwarza program po trochu.
Zestawiane język jest w języku wysokiego poziomu, w której kod jest przekształcany do maszynowego kodu przez kompilator (programu, który przekształca języka wysokiego poziomu na kod maszynowy), a następnie wykonywane przez wykonawcy (inny program do uruchamiania kodu).
Popraw mnie, jeśli moje definicje są błędne.
Teraz wracając do Pythona, jestem trochę zdezorientowany. Wszędzie, gdzie dowiadujesz się, że Python jest językiem interpretowanym, ale jest interpretowany do jakiegoś kodu pośredniego (jak bajt-code lub IL), a nie do kodu maszynowego. Który program wykonuje kod IM? Pomóż mi zrozumieć, w jaki sposób skrypt Python jest obsługiwany i uruchamiany.
źródło
Odpowiedzi:
Po pierwsze, interpretacja / kompilacja nie jest własnością języka, ale właściwością implementacji. W przypadku większości języków większość, jeśli nie wszystkie implementacje, należą do jednej kategorii, więc można zapisać kilka słów, mówiąc, że język jest również interpretowany / kompilowany, ale nadal jest to ważne rozróżnienie, zarówno dlatego, że pomaga w zrozumieniu, jak i dlatego, że istnieje wiele języków z użytecznymi implementacjami obu rodzajów (głównie w dziedzinie języków funkcjonalnych, patrz Haskell i ML). Ponadto istnieją interpretery C i projekty, które próbują skompilować podzbiór języka Python do kodu C lub C ++ (a następnie do kodu maszynowego).
Po drugie, kompilacja nie ogranicza się do kompilacji z wyprzedzeniem do natywnego kodu maszynowego. Kompilator to, bardziej ogólnie, program, który konwertuje program z jednego języka programowania na program w innym języku programowania (prawdopodobnie można nawet mieć kompilator z tym samym językiem wejściowym i wyjściowym, jeśli zastosowane zostaną znaczące transformacje). Kompilatory JIT kompilują się w natywnym kodzie maszynowym w czasie wykonywania , co może zapewnić szybkość bardzo zbliżoną lub nawet lepszą niż kompilacja z wyprzedzeniem (w zależności od testu porównawczego i jakości porównywanych implementacji).
Ale żeby przestać nitpicking i odpowiedzieć na pytanie, które chciałeś zadać: Praktycznie (czytaj: używając nieco popularnej i dojrzałej implementacji), Python jest kompilowany . Nieskompilowany z wyprzedzeniem do kodu maszynowego (tj. „Skompilowany” przez ograniczoną i niepoprawną, ale niestety wspólną definicję), „tylko” skompilowany do kodu bajtowego , ale nadal jest kompilacją z przynajmniej niektórymi zaletami. Na przykład instrukcja
a = b.c()
jest kompilowana do strumienia bajtów, który po zdemontowaniu wygląda trochę jakload 0 (b); load_str 'c'; get_attr; call_function 0; store 1 (a)
. Jest to uproszczenie, w rzeczywistości jest mniej czytelne i nieco bardziej niskiego poziomu - możesz eksperymentować ze standardowymdis
modułem bibliotecznym i zobaczyć, jak wygląda prawdziwa okazja.Ten kod bajtowy jest albo interpretowany (zauważ, że istnieje różnica, zarówno w teorii, jak i w praktyce, między bezpośrednią interpretacją a pierwszą kompilacją do jakiejś pośredniej reprezentacji i interpretacji tego), jak w przypadku implementacji referencyjnej (CPython), lub obie interpretowane i kompilowane do zoptymalizowany kod maszynowy w czasie wykonywania, tak jak w przypadku PyPy .
źródło
Procesor rzeczywiście może zrozumieć tylko kod maszynowy. W przypadku interpretowanych programów ostatecznym celem interpretera jest „interpretacja” kodu programu na kod maszynowy. Jednak zwykle nowoczesny język interpretowany nie interpretuje kodu ludzkiego bezpośrednio, ponieważ jest zbyt mało wydajny.
Interpreter języka Python najpierw odczytuje kod ludzki i optymalizuje go do jakiegoś kodu pośredniego przed interpretacją go na kod maszynowy. Dlatego zawsze potrzebujesz innego programu do uruchomienia skryptu Python, w przeciwieństwie do C ++, w którym możesz bezpośrednio uruchomić skompilowany plik wykonywalny swojego kodu. Na przykład
c:\Python27\python.exe
lub/usr/bin/python
.źródło
Odpowiedź zależy od zastosowanej implementacji Pythona. Jeśli używasz powiedzmy CPython (Standardowa implementacja Pythona) lub Jython (Przeznaczony do integracji z językiem programowania Java), najpierw jest tłumaczony na kod bajtowy , aw zależności od implementacji używanego Pythona, ten kod jest kierowany do odpowiedniego maszyna wirtualna do interpretacji . PVM (Python Virtual Machine) dla CPython i JVM (Java Virtual Machine) dla Jython.
Ale powiedzmy, że używasz PyPy, który jest kolejną standardową implementacją CPython. Byłoby użyć Just-In-Time Compiler .
źródło
Według oficjalnej strony Python jest to język interpretowany.
https://www.python.org/doc/essays/blurb/
...
...
...
źródło
Tak, jest to zarówno język skompilowany, jak i interpretowany. Dlaczego na ogół nazywamy to tłumaczonym językiem?
zobaczyć, jak jest zarówno kompilowana, jak i interpretowana?
Przede wszystkim chcę powiedzieć, że bardziej spodoba ci się moja odpowiedź, jeśli pochodzisz ze świata Java.
W Javie kod źródłowy jest najpierw konwertowany na kod bajtowy za pomocą kompilatora javac, a następnie kierowany do JVM (odpowiedzialnego za generowanie kodu natywnego w celu wykonania). Teraz chcę pokazać, że nazywamy Javę językiem kompilowanym, ponieważ widzimy, że naprawdę kompiluje kod źródłowy i przekazuje plik .class (tylko kod bajtowy) poprzez:
javac Hello.java -------> tworzy plik Hello.class
java Witaj --------> Przekierowanie kodu bajtowego do JVM w celu wykonania
To samo dzieje się z Pythonem, tzn. Najpierw kod źródłowy jest konwertowany na kod bajtowy przez kompilator, a następnie kierowany do PVM (odpowiedzialnego za generowanie kodu natywnego w celu wykonania). Teraz chcę pokazać, że zwykle wywołujemy Python jako język interpretowany, ponieważ kompilacja odbywa się za sceną i kiedy uruchamiamy kod Pythona poprzez:
python Hello.py -------> bezpośrednio wycina kod i widzimy, że dane wyjściowe dowodzą, że kod jest poprawny pod względem składniowym
@ python Hello.py wygląda na to, że wykonuje bezpośrednio, ale tak naprawdę najpierw generuje kod bajtowy, który jest interpretowany przez interpretera w celu wygenerowania kodu natywnego na potrzeby wykonania.
CPython - bierze odpowiedzialność zarówno za kompilację, jak i interpretację.
Spójrz na poniższe linie, jeśli potrzebujesz więcej szczegółów :
Jak już wspomniałem, CPython kompiluje kod źródłowy, ale faktyczna kompilacja odbywa się za pomocą cytonu, następnie interpretacja odbywa się za pomocą CPython
Porozmawiajmy teraz trochę o roli kompilatora Just-In-Time w Javie i Pythonie
W JVM istnieje interpreter Java, który interpretuje kod bajt linia po linii, aby uzyskać natywny kod maszynowy do wykonania, ale gdy kod bajtowy Java jest wykonywany przez interpretera, wykonanie zawsze będzie wolniejsze. Więc jakie jest rozwiązanie? rozwiązaniem jest kompilator Just-In-Time, który wytwarza natywny kod, który można wykonać znacznie szybciej niż można to zinterpretować. Niektórzy dostawcy JVM używają interpretera Java, a niektórzy kompilatora Just-In-Time . Odniesienie: kliknij tutaj
W Pythonie, aby obejść interpreter w celu szybkiego wykonania, użyj innej implementacji Pythona ( PyPy ) zamiast CPython . kliknij tutaj, aby zobaczyć inne implementacje Pythona, w tym PyPy .
źródło
Jeśli (znasz Javę) {
kod Pythona jest konwertowany na kod bajtowy, tak jak robi to Java.
Ten kod bajtowy jest wykonywany ponownie za każdym razem, gdy próbujesz uzyskać do niego dostęp.
} else {
Kod Pythona jest początkowo tłumaczony na coś, co nazywa się bytecode,
który jest dość zbliżony do języka maszynowego, ale nie rzeczywistego kodu maszynowego,
więc za każdym razem, gdy uzyskujemy do niego dostęp lub uruchamiamy, kod bajtowy jest wykonywany ponownie
}
źródło
Prawie możemy powiedzieć, że Python jest językiem interpretowanym. Ale używamy pewnej części jednorazowego procesu kompilacji w Pythonie do konwersji pełnego kodu źródłowego na kod bajtowy, taki jak język Java.
źródło
Dla początkujących
Python automatycznie kompiluje skrypt do skompilowanego kodu, tzw. Kodu bajtowego, przed jego uruchomieniem.
Uruchomienie skryptu nie jest uważane za import i nie zostanie utworzony plik .pyc.
Na przykład, jeśli masz plik skryptu abc.py, który importuje inny moduł xyz.py, po uruchomieniu abc.py, xyz.pyc zostanie utworzony od czasu importu xyz, ale od abc nie zostanie utworzony plik abc.pyc. py nie jest importowane.
źródło
Jest to duże zamieszanie dla osób, które rozpoczęły pracę nad pytonem, a odpowiedzi tutaj są trochę trudne do zrozumienia, więc ułatwię to.
Kiedy instruujemy Python, aby uruchomił nasz skrypt, jest kilka kroków, które wykonuje Python, zanim nasz kod zacznie się rozpadać:
Kiedy wykonujemy kod źródłowy, Python kompiluje go w kod bajtowy. Kompilacja jest krokiem tłumaczenia, a kod bajtowy jest reprezentacją kodu źródłowego niezależną od platformy reprezentacją niskiego poziomu. Zauważ, że bajtowy kod Pythona nie jest binarnym kodem maszynowym (np. Instrukcje dla układu Intel).
W rzeczywistości Python tłumaczy każdą instrukcję kodu źródłowego na instrukcje kodu bajtowego, rozkładając je na poszczególne kroki. Tłumaczenie kodu bajtowego jest wykonywane w celu przyspieszenia wykonania. Kod bajtowy można uruchomić znacznie szybciej niż oryginalne instrukcje kodu źródłowego. Ma rozszerzenie.pyc i zostanie zapisane, jeśli będzie mogło pisać na naszym komputerze.
Zatem następnym razem, gdy uruchomimy ten sam program, Python załaduje plik .pyc i pominie krok kompilacji, chyba że został zmieniony. Python automatycznie sprawdza znaczniki czasowe plików kodu źródłowego i bajtowego, aby wiedzieć, kiedy należy go ponownie skompilować. Jeśli ponownie zapisamy kod źródłowy, kod bajtu jest automatycznie tworzony ponownie przy następnym uruchomieniu programu.
Jeśli Python nie może zapisać plików kodu bajtów na naszym komputerze, nasz program nadal działa. Kod bajtu jest generowany w pamięci i po prostu odrzucany przy wyjściu z programu. Ale ponieważ pliki .pyc skracają czas uruchamiania, możemy chcieć się upewnić, że został napisany dla większych programów.
Podsumujmy, co dzieje się za kulisami. Kiedy Python wykonuje program, Python wczytuje plik .py do pamięci i analizuje go w celu uzyskania kodu bajtowego, a następnie uruchamia się. Dla każdego modułu importowanego przez program Python najpierw sprawdza, czy istnieje wstępnie skompilowana wersja kodu bajtowego w .pyo lub .pyc, która ma znacznik czasu odpowiadający jego plikowi .py. Python używa wersji kodu bajtowego, jeśli istnieje. W przeciwnym razie analizuje plik .py modułu, zapisuje go w pliku .pyc i używa właśnie utworzonego kodu bajtowego.
Pliki z kodami bajtów są również jednym ze sposobów przesyłania kodów w języku Python. Python nadal uruchomi program, jeśli wszystko, co może znaleźć, to pliki.p.p, nawet jeśli nie ma tam oryginalnych plików źródłowych .py.
Python Virtual Machine (PVM)
Gdy nasz program zostanie skompilowany do kodu bajtowego, jest wysyłany do wykonania w Python Virtual Machine (PVM). PVM nie jest osobnym programem. Nie musi być instalowany sam. W rzeczywistości PVM to po prostu duża pętla, która iteruje kolejno nasze instrukcje bajtów, aby wykonywać swoje operacje. PVM to silnik wykonawczy Pythona. Jest zawsze obecny jako część systemu Python. To składnik, który naprawdę uruchamia nasze skrypty. Technicznie jest to tylko ostatni krok tak zwanego interpretera języka Python.
źródło
Kod Pythona, który piszesz, jest kompilowany do kodu bajtowego Pythona, który tworzy plik z rozszerzeniem .pyc. Jeśli się kompiluje, znowu pytanie brzmi: dlaczego nie skompilować języka.
Zauważ, że nie jest to kompilacja w tradycyjnym tego słowa znaczeniu. Zazwyczaj mówimy, że kompilacja przyjmuje język wysokiego poziomu i konwertuje go na kod maszynowy. Ale jest to swego rodzaju kompilacja. Skompilowany do kodu pośredniego, a nie do kodu maszynowego (mam nadzieję, że teraz go masz).
Wracając do procesu wykonywania, twój kod bajtowy, obecny w pliku pyc, utworzony w kroku kompilacji, jest następnie wykonywany przez odpowiednie maszyny wirtualne, w naszym przypadku CPython VM. Znacznik czasu (nazywany magiczną liczbą) służy do sprawdzenia, czy. plik py jest zmieniany lub nie, w zależności od tego, jaki nowy plik pyc jest tworzony. Jeśli pyc ma bieżący kod, po prostu pomija krok kompilacji.
źródło
Python (interpreter) jest kompilowany .
Dowód: nawet nie skompiluje kodu, jeśli zawiera błąd składniowy .
Przykład 1:
Wynik:
Przykład 2:
Wynik:
źródło