Por mais diversificados que sejam, existem alguns conceitos comuns que todas as linguagens de programação modernas sérias compartilham. Dois deles são o núcleo da resposta para suas perguntas acima.
Quais etapas acontecem entre eu pressionar o botão Enter e o código da máquina gerado a partir do meu código python sendo executado na minha CPU?
O código é analisado, analisado e alimentado em um intérprete. Isso é tudo sobre uma área muito importante da ciência da computação conhecida como teoria dos compiladores . Um compilador é um programa que converte código de um idioma (seu código-fonte) para outro idioma (normalmente código de máquina, embora existam "transpilers" que traduzem de um idioma de alto nível para outro). Este é um tópico realmente enorme que você poderia passar anos pesquisando, mas aqui está a versão básica:
O compilador começa com um analisador , uma rotina que lê seu código-fonte e aplica as regras de sintaxe da linguagem a ele para descobrir se faz sentido como código Python (no seu caso) válido. Caso contrário, o analisador emitirá um erro e o compilador falhará, mas, se o fizer, o analisador emitirá o que é conhecido como Árvore de Sintaxe Abstrata, ou AST, abreviado. O AST é uma estrutura de dados em árvore cujos nós contêm um elemento da sintaxe. Por exemplo, se você disser x = 5, poderá terminar com um BinaryExpressionnó com um operatorvalor de =, um Leftvalor de ReferenceExpression(x)e um Rightvalor de IntegerLiteralExpression(5). Todo o seu programa pode ser representado por uma grande árvore como esta.
Depois que o analisador produz um AST, a segunda fase é a análise semântica . Em inglês simples, isso significa "descobrir o que esse AST significa". Ele verifica o AST para determinar se você fez algo ilegal, embora seja uma análise válida (por exemplo, tentando chamar uma função de 1 argumento com 3 argumentos) e gera erros se você o fizer. Caso contrário, ele analisa o AST e realiza edições para facilitar a compreensão de uma máquina.
A terceira fase é a geração de código. Depois de ter um AST totalmente analisado, simplificado e válido, você o alimenta no gerador, que percorre o AST e produz código no idioma de saída. Este é o seu produto acabado.
Com o Python, ele usa um intérprete em vez de um compilador. Um intérprete funciona exatamente da mesma maneira que um compilador, com uma diferença: em vez da geração de código, ele carrega a saída na memória e a executa diretamente no seu sistema. (Os detalhes exatos de como isso acontece podem variar bastante entre diferentes idiomas e diferentes intérpretes.)
E como isso se relaciona com o sistema de tempo de execução Python e / ou biblioteca?
Todos os idiomas, exceto os mais simples, vêm com um conjunto de funções predefinidas que são importantes para uma grande porcentagem de usuários e que dificilmente seriam implementados por um motivo ou outro. O código deles pode chamar essas funções sem precisar de bibliotecas de terceiros. (Por exemplo, em Python, você printenvia uma saída para stdout. Boa sorte implementando isso por conta própria!) Esse conjunto de funções geralmente é coletado em uma biblioteca compartilhada na qual o código pode ser chamado em tempo de execução, e é por isso que é conhecido como a biblioteca de tempo de execução do idioma ou simplesmente "o tempo de execução" para abreviar.