Executando verificação de segurança...
11

A verdade é que muitos devs ainda não sabem como o Python roda seu código… você sabe? 🤫

  1. Leitura → Parsing
    Quando você roda python app.py, o CPython (versão "oficial" do Python, escrita em C) lê todo o texto e verifica se a sintaxe faz sentido. Pense num corretor ortográfico que procura vírgulas fora do lugar.

  2. Tradução rápida → Bytecode
    Em seguida, o CPython faz uma tradução intermediária chamada bytecode – é como transformar português em "portunhol" antes de chegar ao espanhol.
    Arquivo gerado: __pycache__/app.cpython-312.pyc

    Exemplo de bytecode:

    0 LOAD_CONST 1 (10) # carrega o número 10
    2 LOAD_CONST 2 (20) # carrega o número 20
    4 BINARY_ADD        # soma 10 + 20
    6 RETURN_VALUE      # devolve 30
    
  3. Execução → Python Virtual Machine
    Agora quem assume é a Python VM, um programa que interpreta o bytecode linha a linha, decidindo o que fazer em cada etapa (alocar memória, somar valores, coletar lixo, etc.).

  4. Cache esperto → __pycache__
    O bytecode é guardado na pasta __pycache__. Da próxima vez que você rodar o mesmo arquivo, essa etapa de tradução é pulada e o script abre mais rápido.

Resumindo em uma frase

Python compila para bytecode e depois interpreta esse bytecode. Por isso dizemos que ele é ao mesmo tempo compilado e interpretado – combina produtividade com portabilidade.

Carregando publicação patrocinada...
8

Sobre o diretório __pycache__, vale lembrar que ele só guarda os arquivos de módulos que são importados.

Ou seja, suponha que eu rodo python meu_script.py e dentro dele tem um import meu_modulo. Então no diretório __pycache__ será gerado o arquivo correspondente ao meu_modulo.py (geralmente no formato arquivo-versão.pyc, então no meu caso o arquivo resultante seria __pycache__/meu_modulo.cpython-312.pyc já que estou usando Python 3.12). Mas não será gerado um arquivo correspondente ao meu_script.py.

Inclusive, se eu rodar o código do módulo diretamente (por exemplo, python meu_modulo.py em vez de rodar outro código que o importe), neste caso ele não é adicionado ao __pycache__.

Isso está descrito na documentação, que também mostra que vc pode adicionar manualmente qualquer arquivo ao __pycache__, usando o módulo py_compile. Ex:

import py_compile
py_compile.compile('arquivo.py')

Desta forma, vc pode adicionar qualquer arquivo ao __pycache__. Mas por padrão, ele terá apenas os módulos que são importados no código que estiver rodando.


Inclusive, na PEP 3147 (que definiu o mecanimo por trás do diretório __pycache__) tem um diagrama bem didático, e repare como o ponto inicial é um import:

Diagrama do mecanismo de importação de um módulo

1