Mam pewne problemy ze zrozumieniem koncepcji, a runtime library
zwł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?
Odpowiedzi:
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.
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ć zBinaryExpression
węzłem ooperator
wartości=
,Left
wartościReferenceExpression(x)
iRight
wartościIntegerLiteralExpression(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.)
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ściowestdout
. 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.źródło
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ół”.
źródło