Se o Python for interpretado, o que são arquivos .pyc?

1084

Fui dado a entender que Python é uma linguagem interpretada ...
No entanto, quando olho para o meu código-fonte Python, vejo .pycarquivos que o Windows identifica como "Arquivos Python compilados".

De onde eles vêm?

froadie
fonte
3
Consulte stackoverflow.com/questions/11433579/… para uma justificativa. Em uma palavra: velocidade.
user7610
3
@GregSchmit Você está certo que esta pergunta não é a duplicata, mas MrBultitude está correto em dizer que o momento é irrelevante. "Geralmente, uma pergunta recente será encerrada como duplicada de uma pergunta antiga, mas essa não é uma regra absoluta. A regra geral é manter a pergunta com a melhor coleção de respostas e fechar a outra como duplicada."
precisa saber é o seguinte
Isso significa que até o python possui o 'Escreva uma vez, execute em qualquer lugar', como o Java.?
Mrak Vladar
2
@MrakVladar Mesmo Java é "Escreva uma vez, execute em qualquer lugar [que você tenha uma JVM]". Python não é diferente; é "executado em qualquer lugar que você tenha uma máquina virtual Python". A grande diferença é que a maioria das implementações Python combina o compilador e o intérprete em um executável, em vez de separá-los como javae javac.
Chepner # 7/19

Respostas:

661

Eles contêm código de bytes , que é o que o interpretador Python compila a fonte. Esse código é então executado pela máquina virtual do Python.

A documentação do Python explica a definição assim:

Python é uma linguagem interpretada, em oposição a uma linguagem compilada, embora a distinção possa ser imprecisa devido à presença do compilador de bytecodes. Isso significa que os arquivos de origem podem ser executados diretamente sem criar explicitamente um executável que é executado.

descontrair
fonte
10
Interessante, obrigado. Então, o Python é considerado uma linguagem puramente interpretada?
froadie
194
@roadroadie: um idioma não é "interpretado" ou "compilado" como tal. Uma implementação específica pode ser um intérprete ou um compilador (ou um híbrido ou um compilador JIT).
Joachim Sauer
30
Um teste de 'compilado': ele é compilado com instruções reais da máquina? O bytecode do Python não é instruções da máquina, nem instruções Java 'JVM', portanto, nenhuma dessas linguagens é compilada por essa definição. Mas ambos são 'compilados' para um código intermediário de 'máquina abstrata' e são muito mais rápidos do que executar o programa interpretando mais ou menos diretamente o código-fonte (que é o que o BASIC da velha escola faz).
Greggo
20
Ser pedante, 'compilado' significa 'traduzido'. O Python é então compilado em um bytecode. AFAIK, apenas o Bash é realmente interpretado, todas as outras linguagens "interpretadas" populares são todas compiladas em um bytecode.
precisa saber é o seguinte
13
Na verdade, são instruções da máquina, mas não instruções nativas da máquina para a CPU física do host. Por isso, por que chamamos de VM? Como o esperanto na linguagem assembly realmente. Hoje em dia temos até código nativo para CPUs fictícias (mas ainda emuladas) (o esforço de Mojang para atrair as crianças). Rexx foi (ou poderia ser) realmente interpretado, e BAT e CMD (e DCL) são interpretados.
Mckenzm
994

Fui dado a entender que Python é uma linguagem interpretada ...

Esse meme popular está incorreto, ou melhor, construído sobre um mal-entendido dos níveis (naturais) da linguagem: um erro semelhante seria dizer "a Bíblia é um livro de capa dura". Deixe-me explicar esse símile ...

"A Bíblia" é "um livro" no sentido de ser uma classe de (objetos físicos reais identificados como) livros; os livros identificados como "cópias da Bíblia" devem ter algo fundamental em comum (o conteúdo, embora até esses possam estar em idiomas diferentes, com traduções aceitáveis ​​diferentes, níveis de notas de rodapé e outras anotações) - no entanto, esses livros são perfeitamente bem permitido diferir em uma infinidade de aspectos que não são considerados fundamentais - tipo de encadernação, cor da encadernação, fontes usadas na impressão, ilustrações, se houver, amplas margens graváveis ​​ou não, números e tipos de marcadores embutidos , e assim por diante.

É bem possível que uma impressão típica da Bíblia esteja realmente encadernada - afinal, é um livro que costuma ser lido várias vezes, marcado em vários lugares, folheado em busca de indicadores de capítulo e verso , etc, etc, e uma boa ligação de capa dura pode fazer com que uma determinada cópia dure mais tempo sob esse uso. No entanto, essas são questões mundanas (práticas) que não podem ser usadas para determinar se um determinado objeto real do livro é uma cópia da Bíblia ou não: impressões em brochura são perfeitamente possíveis!

Da mesma forma, Python é "uma linguagem" no sentido de definir uma classe de implementações de linguagem que devem ser semelhantes em alguns aspectos fundamentais (sintaxe, a maioria das semânticas, exceto aquelas partes daquelas em que é explicitamente permitido diferir), mas são totalmente permitidas. diferir em quase todos os detalhes da "implementação" - incluindo como eles lidam com os arquivos de origem fornecidos, se eles compilam os fontes para alguns formulários de nível inferior (e, se houver, qual formulário - e se eles salvam esses formulários compilados, em disco ou em outro local), como eles executam os referidos formulários e assim por diante.

A implementação clássica, CPython, geralmente é chamada apenas de "Python", mas é apenas uma das várias implementações de qualidade de produção, lado a lado com o IronPython da Microsoft (que compila códigos CLR, como ".NET"), Jython (que é compilado com códigos da JVM), PyPy (que é escrito no próprio Python e pode ser compilado em uma enorme variedade de formulários de "back-end", incluindo a linguagem de máquina gerada "just-in-time"). Eles são todos Python (== "implementações da linguagem Python"), assim como muitos objetos de livro superficialmente diferentes podem ser Bíblias (== "cópias da Bíblia").

Se você estiver interessado no CPython especificamente: ele compila os arquivos de origem em um formulário de nível inferior específico do Python (conhecido como "bytecode"), o faz automaticamente quando necessário (quando não há um arquivo de bytecode correspondente a um arquivo de origem ou o arquivo bytecode é mais antigo que o código-fonte ou compilado por uma versão diferente do Python) geralmente salva os arquivos de bytecode em disco (para evitar recompilá-los no futuro). O OTOH IronPython normalmente compila os códigos CLR (salvando-os em disco ou não, dependendo) e os códigos Jython para JVM (salvando-os em disco ou não - ele usará a .classextensão se os salvar).

Esses formulários de nível inferior são executados por "máquinas virtuais" apropriadas, também conhecidas como "intérpretes" - a VM CPython, o tempo de execução .Net, a Java VM (também conhecida como JVM), conforme apropriado.

Portanto, nesse sentido (o que as implementações típicas fazem), o Python é uma "linguagem interpretada" se, e somente se, C # e Java: todos eles têm uma estratégia de implementação típica para produzir primeiro o bytecode e depois executá-lo por meio de uma VM / intérprete. .

É mais provável que o foco esteja em quão "pesado", lento e de alta cerimônia é o processo de compilação. O CPython foi projetado para compilar o mais rápido possível, o mais leve possível, com o mínimo de cerimônia possível - o compilador faz muito pouca verificação e otimização de erros, para que possa executar rapidamente e em pequenas quantidades de memória, o que, por sua vez, permite seja executado de forma automática e transparente sempre que necessário, sem que o usuário precise saber que há uma compilação em andamento na maioria das vezes. Java e C # geralmente aceitam mais trabalho durante a compilação (e, portanto, não realizam a compilação automática) para verificar os erros mais detalhadamente e realizar mais otimizações. É um continuum de escamas cinzentas, não uma situação em preto ou branco,

Alex Martelli
fonte
2
Bela resposta. Apenas uma pequena correção para o último parágrafo: Python foi projetado para compilar o mais rápido possível (etc.). Desta vez, é realmente a linguagem, com sua falta de sistema de tipo estático e outras coisas. Quando as pessoas falam sobre idiomas "interpretados", geralmente significam idiomas "dinâmicos".
Elazar
2
@Elazar, na verdade, outras implementações do Python, como o PyPy, que não têm pressa em compilar, conseguem fazer a análise mais completa exigida pela falta de digitação estática e produzem compilação just-in-time para o código da máquina (aumentando a velocidade programas de execução demorada várias vezes).
Alex Martelli
Onde o Cython se encaixa aqui? Você consideraria uma linguagem diferente ou é uma implementação em Python? Além disso, esse meme de "interpretado" vs compilado talvez seja apenas uma confusão de terminologia porque a VM do Python é frequentemente chamada de "intérprete"? Seria igualmente válido chamar os intérpretes de tempo de execução da JVM ou .NET. Ambos principalmente interpretar bytecode em código de máquina JIT (com algumas exceções otimização de cache)
Davos
181

Não existe linguagem interpretada. Se um intérprete ou um compilador é usado é apenas uma característica da implementação e não tem absolutamente nada a ver com o idioma.

Cada idioma pode ser implementado por um intérprete ou um compilador. A grande maioria dos idiomas possui pelo menos uma implementação de cada tipo. (Por exemplo, existem intérpretes para C e C ++ e compiladores para JavaScript, PHP, Perl, Python e Ruby.) Além disso, a maioria das implementações de linguagem moderna na verdade combina um intérprete e um compilador (ou até vários compiladores).

Uma linguagem é apenas um conjunto de regras matemáticas abstratas. Um intérprete é uma das várias estratégias de implementação concretas para um idioma. Esses dois vivem em níveis de abstração completamente diferentes. Se o inglês fosse um idioma digitado, o termo "idioma interpretado" seria um erro de tipo. A afirmação "Python é uma linguagem interpretada" não é apenas falsa (porque ser falsa implicaria que a afirmação faz sentido, mesmo que esteja errada), simplesmente não faz sentido , porque uma linguagem nunca pode ser definida como "interpretado".

Em particular, se você observar as implementações existentes no Python, estas são as estratégias de implementação que estão usando:

  • IronPython: compila em árvores DLR que o DLR compila no bytecode CIL. O que acontece com o bytecode CIL depende de qual CLI VES você está executando, mas o Microsoft .NET, GNU Portable.NET e Novell Mono acabarão por compilá-lo no código de máquina nativo.
  • Jython: interpreta o código-fonte do Python até identificar os caminhos do código ativo, que depois compila no bytecode da JVML. O que acontece com o bytecode da JVML depende de qual JVM você está executando. Maxine irá compilá-lo diretamente para código nativo não otimizado até identificar os caminhos de código quente, que depois recompila para código nativo otimizado. O HotSpot primeiro interpretará o bytecode da JVML e, em seguida, compilará os caminhos do código quente para o código da máquina otimizado.
  • PyPy: compila no bytecode do PyPy, que é interpretado pela VM do PyPy até identificar os caminhos de código de acesso que compila no código nativo, bytecode JVML ou bytecode CIL, dependendo da plataforma em que você está executando.
  • CPython: compila no bytecode do CPython que ele interpreta.
  • Python sem pilha: compila no bytecode do CPython que ele interpreta.
  • Unladen Swallow: compila no bytecode CPython que ele interpreta até identificar os caminhos de código quente que compila no LLVM IR que o compilador LLVM compila no código da máquina nativo.
  • Cython: compila código Python em código C portátil, que é compilado com um compilador C padrão
  • Nuitka: compila código Python em código C ++ dependente da máquina, que é compilado com um compilador C padrão

Você pode perceber que cada uma das implementações nessa lista (além de outras que eu não mencionei, como tinypy, Shedskin ou Psyco) tem um compilador. De fato, até onde eu sei, atualmente não existe uma implementação do Python que seja puramente interpretada, não existe uma implementação planejada e nunca houve essa implementação.

Não apenas o termo "linguagem interpretada" não faz sentido, mesmo que você a interprete como significando "linguagem com implementação interpretada", mas claramente não é verdade. Quem lhe disse isso, obviamente não sabe do que está falando.

Em particular, os .pycarquivos que você está vendo são armazenados em cache por códigos de código produzidos pelo CPython, Stackless Python ou Unladen Swallow.

Jörg W Mittag
fonte
5
O básico da velha escola, como o MSBASIC, não tinha forma intermediária. O programa foi interpretado diretamente do formulário de origem (ou código-fonte próximo, um formulário no qual as palavras-chave eram representadas por tokens de 1 byte e as linhas # por ints binários de 2 bytes, mas o resto era apenas ASCII). Então, de fato, um 'ir' levaria diferentes quantidades de tempo, dependendo de quantas linhas de origem ele teve que pesquisar procurando o destino correspondente. Expressões como a * b-2 * cos (x) foram efetivamente analisadas novamente toda vez que foram executadas.
Greggo
4
@greggo: E se você quiser ir além da velha escola, a versão original do BASIC era um compilador de código nativo. Isso deve provar o quão ridícula é a noção de uma linguagem "compilada" ou "interpretada".
Jörg W Mittag 06/04
Obrigado por explicar como os vários compiladores / intérpretes python se comportam. Gostaria de saber se existem bons compiladores Python que já geram C ou JavaScript eficientes. Parece muito factível, talvez não para consumo em massa, mas para um subconjunto razoável de Python, pelo menos. Também me pergunto o que é Cython.
personal_cloud
O Cython foi mencionado no SciPy 2009, mas posso perdoá-lo por não saber sobre isso em 2010 (aqui estou em 2017, apenas agora aprendendo sobre isso). Ainda precisamos encontrar um exemplo de JavaScript ... Jython não faz sentido para mim (o Java já não estava morto em 2009? Bem, hmm, talvez não ... o aumento do C ++ não era tão bom naquela época)
personal_cloud
1
@personal_cloud: Não sigo exatamente o seu comentário. Sim, claro, eu sei sobre o Cython, mas o que isso tem a ver com alguma coisa? Não é uma implementação do Python, é uma linguagem completamente diferente. Além disso, não é realmente difícil encontrar um exemplo de JavaScript; de fato, todas as implementações de JavaScript mainstream atualmente existentes possuem compiladores. Por fim, o Jython é uma implementação do Python como qualquer outra implementação do Python. E é uma implementação de uma linguagem na plataforma Java, assim como qualquer outra implementação de linguagem na plataforma Java.
Jörg W Mittag
61

Eles são criados pelo intérprete Python quando um .pyarquivo é importado e contêm o "bytecode compilado" do módulo / programa importado, com a idéia de que a "tradução" do código fonte para o bytecode (que só precisa ser feita uma vez) pode ser ignorado em imports subsequentes, se o .pycfor mais novo que o .pyarquivo correspondente , acelerando um pouco a inicialização. Mas ainda é interpretado.

Tim Pietzcker
fonte
10
Verdade. Exceto que muitas bibliotecas principais do Python são escritas em C. Portanto, partes do python são interpretadas, parte é executada em C. Você pode fazer o mesmo com seus próprios bits de código sensíveis ao desempenho.
bwawok
44

Para acelerar o carregamento de módulos, o Python armazena em cache o conteúdo compilado dos módulos em .pyc.

O CPython compila seu código-fonte em "código de bytes" e, por razões de desempenho, armazena em cache esse código de bytes no sistema de arquivos sempre que o arquivo de origem é alterado. Isso torna o carregamento dos módulos Python muito mais rápido, porque a fase de compilação pode ser ignorada. Quando seu arquivo de origem é foo.py, o CPython armazena em cache o código de bytes em um arquivo foo.pyc ao lado da fonte.

No python3, o mecanismo de importação do Python é estendido para gravar e pesquisar arquivos de cache de código de bytes em um único diretório dentro de cada diretório de pacotes do Python. Este diretório será chamado __pycache__.

Aqui está um fluxograma descrevendo como os módulos são carregados:

insira a descrição da imagem aqui

Para maiores informações:

ref: PEP3147
ref: arquivos Python “compilados”

hxysayhi
fonte
38

ISTO É PARA INICIANTES,

O Python compila automaticamente seu script no código compilado, chamado código de bytes, antes de executá-lo.

A execução de um script não é considerada uma importação e nenhum .pyc será criado.

Por exemplo, se você tiver um arquivo de script abc.py que importe outro módulo xyz.py , ao executar o abc.py , o xyz.pyc será criado desde que o xyz foi importado, mas nenhum arquivo abc.pyc será criado desde o abc. py não está sendo importado.

Se você precisar criar um arquivo .pyc para um módulo que não seja importado, poderá usar os módulos py_compilee compileall.

O py_compilemódulo pode compilar manualmente qualquer módulo. Uma maneira é usar a py_compile.compilefunção nesse módulo interativamente:

>>> import py_compile
>>> py_compile.compile('abc.py')

Isso gravará o arquivo .pyc no mesmo local que o abc.py (você pode substituí-lo pelo parâmetro opcional cfile).

Você também pode compilar automaticamente todos os arquivos em um diretório ou diretórios usando o módulo compileall.

python -m compileall

Se o nome do diretório (o diretório atual neste exemplo) for omitido, o módulo compila tudo o que é encontrado em sys.path

MAX
fonte
6
e qual é o benefício de compilar para obter o abc.py?
Saher Ahwal 14/02
@SaherAhwal Um benefício que consigo pensar é na verificação de sintaxe.
Yi Bao
20

O Python (pelo menos a implementação mais comum) segue um padrão de compilação da fonte original em códigos de bytes e, em seguida, na interpretação dos códigos de bytes em uma máquina virtual. Isso significa (novamente, a implementação mais comum) não é um intérprete puro nem um compilador puro.

O outro lado disso, no entanto, é que o processo de compilação está oculto na maior parte - os arquivos .pyc são basicamente tratados como um cache; eles aceleram as coisas, mas você normalmente não precisa estar ciente delas. Ele os invalida e os recarrega automaticamente (recompila o código-fonte) quando necessário com base nos registros de data / hora do arquivo.

A única vez em que vi um problema com isso foi quando um arquivo de bytecode compilado de alguma forma obteve um carimbo de data / hora no futuro, o que significava que sempre parecia mais novo que o arquivo de origem. Como parecia mais novo, o arquivo de origem nunca foi recompilado; portanto, independentemente das alterações feitas, eles foram ignorados ...

Jerry Coffin
fonte
12

O arquivo * .py do Python é apenas um arquivo de texto no qual você escreve algumas linhas de código. Quando você tenta executar este arquivo usando, diga "python filename.py"

Este comando chama a máquina virtual Python. A Máquina Virtual Python possui 2 componentes: "compilador" e "intérprete". O intérprete não pode ler diretamente o texto no arquivo * .py, portanto, esse texto é primeiro convertido em um código de bytes direcionado ao PVM (não hardware, mas PVM) . O PVM executa esse código de bytes. O arquivo * .pyc também é gerado, como parte da execução, que executa sua operação de importação no arquivo no shell ou em algum outro arquivo.

Se esse arquivo * .pyc já for gerado, toda vez que você executar / executar seu arquivo * .py, o sistema carregará diretamente o arquivo * .pyc, o que não precisará de nenhuma compilação (isso economizará alguns ciclos de máquina do processador).

Depois que o arquivo * .pyc é gerado, não há necessidade do arquivo * .py, a menos que você o edite.

Vishal Mopari
fonte
7

O código Python passa por 2 estágios. O primeiro passo compila o código em arquivos .pyc, que na verdade é um bytecode. Em seguida, esse arquivo .pyc (bytecode) é interpretado usando o interpretador CPython. Por favor, consulte este link. Aqui, o processo de compilação e execução de código é explicado em termos fáceis.

Tango
fonte