Jak faktycznie działa środowisko wykonawcze Python?

26

Mam pewne problemy ze zrozumieniem koncepcji, a runtime libraryzwłaszcza Pythona. Napisałem więc trochę programu pythonowego hello world i zamierzam go uruchomić, więc piszę python ./hello_world.py.

Jakie kroki zdarzają się między naciśnięciem przycisku Enter a kodem maszynowym wygenerowanym z mojego kodu python wykonywanego na moim CPU? A jak to się ma do systemu wykonawczego Python i / lub biblioteki?

hgiesel
źródło
Te dwa wątki dają doskonały wgląd w środowisko wykonawcze Pythona - czy Python jest interpretowany, kompilowany, czy oba? & Czy interpretuje się Python (np. JavaScript lub PHP)? . Środowisko wykonawcze i biblioteka środowiska wykonawczego to nie to samo. Odwzorowanie go na znany mi świat .NET - Common Language Runtime (CLR) i Framework / Base Class Library (FCL / BCL) to nie to samo.
RBT,

Odpowiedzi:

33

Pomimo tego, że są tak różnorodni, istnieje kilka wspólnych koncepcji, które dzielą wszystkie poważne, nowoczesne języki programowania. Dwa z nich stanowią rdzeń odpowiedzi na powyższe pytania.

Jakie kroki zdarzają się między naciśnięciem przycisku Enter a kodem maszynowym wygenerowanym z mojego kodu python wykonywanego na moim CPU?

Kod jest analizowany, analizowany i wprowadzany do interpretera. Chodzi o bardzo ważny obszar informatyki zwany teorią kompilatora . Kompilator to program, który tłumaczy kod z jednego języka (kodu źródłowego) na inny język (zazwyczaj kod maszynowy, chociaż istnieją „transpilatory”, które tłumaczą z jednego języka wysokiego poziomu na inny). To naprawdę ogromny temat, który możesz poświęcić lat na badania, ale oto podstawowa wersja:

Kompilator zaczyna się od parsera , procedury, która odczytuje kod źródłowy i stosuje do niego reguły składniowe języka, aby dowiedzieć się, czy ma on sens jako poprawny kod Pythona (w twoim przypadku). Jeśli tak się nie stanie, analizator składni wyrzuci błąd, a kompilator wyskoczy, ale jeśli tak, analizator wyśle ​​to, co jest znane jako abstrakcyjne drzewo składni, lub w skrócie AST. AST jest drzewną strukturą danych, której każdy z węzłów zawiera element składni. Na przykład, jeśli powiesz x = 5, możesz skończyć z BinaryExpressionwęzłem o operatorwartości =, Leftwartości ReferenceExpression(x)i Rightwartości IntegerLiteralExpression(5). Twój cały program może być reprezentowany przez takie wielkie drzewo.

Gdy parser wytworzy AST, drugą fazą jest analiza semantyczna . Mówiąc wprost, oznacza to „dowiedzieć się, co oznacza ten AST”. Sprawdza AST, aby ustalić, czy zrobiłeś coś, co jest nielegalne, mimo że jest to poprawna analiza (na przykład próba wywołania funkcji 1-argumentowej z 3 argumentami), i jeśli to zrobisz, wywołuje błędy. W przeciwnym razie analizuje AST i dokonuje edycji, aby ułatwić zrozumienie maszyny.

Trzecią fazą jest generowanie kodu. Po w pełni przeanalizowanym, uproszczonym, poprawnym AST, podajesz go do generatora, który prowadzi AST i generuje kod w języku wyjściowym. To jest twój gotowy produkt.

W Pythonie używa interpretera, a nie kompilatora. Interpreter działa dokładnie tak samo jak kompilator, z jedną różnicą: zamiast generowania kodu ładuje dane wyjściowe do pamięci i wykonuje je bezpośrednio w systemie. (Dokładne szczegóły tego, jak to się dzieje, mogą się znacznie różnić między różnymi językami i różnymi tłumaczami.)

A jak to się ma do systemu wykonawczego Python i / lub biblioteki?

Wszystkie języki oprócz najprostszych są wyposażone w zestaw predefiniowanych funkcji, które są ważne dla dużego odsetka użytkowników i byłoby trudne dla użytkowników do samodzielnego wdrożenia z tego czy innego powodu. Ich kod może wywoływać te funkcje bez potrzeby korzystania z bibliotek stron trzecich. (Na przykład w Pythonie masz print, który wysyła dane wyjściowe stdout. Powodzenia we wdrażaniu go samodzielnie!) Ten zestaw funkcji jest na ogół gromadzony we wspólnej bibliotece, do której kod może wywoływać w czasie wykonywania, dlatego jest znany jako biblioteka środowiska wykonawczego języka lub po prostu „środowisko wykonawcze” w skrócie.

Mason Wheeler
źródło
Więc mój kod jest przekazywany do innego programu (systemu wykonawczego Python), który robi to wszystko i kończy się, gdy mój kod się skończy (i oczywiście po czyszczeniu)?
hgiesel
@hgiesel Uważam, że w przypadku Pythona tłumacz jest częścią środowiska wykonawczego. Nie dotyczy to każdego języka. oczywiście, ale jest to dość powszechne wśród języków interpretowanych.
Mason Wheeler,
5

Standardowa implementacja Pythona jest maszyną wirtualną z kodem bajtowym. Oznacza to, że kod maszynowy ( kody operacyjne z zestawu kodów operacyjnych twojego procesora) nie jest generowany z twojego programu. Opcje są wybierane tylko spośród tych, które są już skompilowane na maszynie wirtualnej, podczas gdy maszyna wirtualna interpretuje kod bajtu.

Sposób, w jaki twój program zamienia się w kod bajtowy, to nieco inne pytanie, ale krótka odpowiedź brzmi „poprzez kompilację, tak jak każde inne tłumaczenie w dół”.

Kilian Foth
źródło