Por que compilar código Python?

241

Por que você compilaria um script Python? Você pode executá-los diretamente a partir do arquivo .py e ele funciona bem. Existe uma vantagem de desempenho ou algo assim?

Percebo também que alguns arquivos no meu aplicativo são compilados em .pyc, enquanto outros não, por que isso?

ryeguy
fonte
Você também pode observar que, incluindo a inicialização mais rápida do seu aplicativo, você também ganha em segurança, se não conseguir compartilhar seu código, se for um segredo corporativo.
Please_Dont_Bully_Me_SO_Lords
@PSyLoCKe Você realmente, realmente não. O bytecode do Python é realmente legível, porque o compilador não precisa ofuscá-lo para otimizá-lo. (Não que otimiza muito ...)
wizzwizz4
1
A razão pela qual alguns arquivos são compilados automaticamente é porque são importados; por exemplo, se você usar import mylib.py, o Python será compilado mylib.pypara que futuras importinstruções sejam executadas um pouco mais rápido. Se você mudar mais tarde mylib.py, então ele vai ter compilado-re próxima vez que for importado (Python usa a data do arquivo para ver que isso acontece.)
fyngyrz

Respostas:

269

É compilado no bytecode, que pode ser usado muito, muito, muito mais rápido.

A razão pela qual alguns arquivos não são compilados é que o script principal, com o qual você invoca, python main.pyé recompilado toda vez que você executa o script. Todos os scripts importados serão compilados e armazenados no disco.

Adição importante de Ben Blank :

Vale a pena notar que, enquanto a execução de um script compilado tem um tempo de inicialização mais rápido (como não precisa ser compilado), não é executada mais rapidamente.

Georg Schölly
fonte
259
Vale a pena notar que, enquanto a execução de um script compilado tem um tempo de inicialização mais rápido (como não precisa ser compilado), não é executada mais rapidamente.
22411 Ben Blank
24
Um equívoco comum. Obrigado por compartilhar.
matpie
1
Além de não exigir compilação, o arquivo .pyc é quase invariavelmente menor. Especialmente se você comentar muito. Um dos meus é 28419 como .py, mas apenas 17879 como .pyc - portanto, o tempo de carregamento também é melhor. Finalmente, você pode pré-compilar scripts de nível superior desta maneira: python -m compileall myscript.py
fyngyrz
1
Existe alguma diferença no consumo de memória? Estou testando Python em dispositivos incorporados com base em mips cpu com apenas 64 MB de RAM, então existe alguma vantagem no uso de memória ao iniciar uma versão compilada de script python?
valentt 14/09/14
1
@valentt: Provavelmente não. Não sei muito sobre os elementos internos do Python, mas não acho que a análise do bytecode consiga muita memória no Python. Não consigo pensar em algo que precise de muita memória para lembrar de algum estado.
Georg Schölly
80

O arquivo .pyc é Python que já foi compilado em código de bytes. O Python executa automaticamente um arquivo .pyc se encontrar um com o mesmo nome que um arquivo .py que você chama.

"Uma introdução ao Python" diz isso sobre arquivos Python compilados:

Um programa não roda mais rápido quando é lido de um arquivo '.pyc' ou '.pyo' do que quando é lido de um arquivo '.py'; a única coisa mais rápida nos arquivos '.pyc' ou '.pyo' é a velocidade com que eles são carregados.

A vantagem de executar um arquivo .pyc é que o Python não precisa suportar a sobrecarga de compilá-lo antes de executá-lo. Como o Python compilaria com código de bytes antes de executar um arquivo .py de qualquer maneira, não deve haver nenhuma melhoria de desempenho além disso.

Quanta melhoria você pode obter ao usar arquivos .pyc compilados? Isso depende do que o script faz. Para um script muito breve que simplesmente imprima "Hello World", a compilação pode constituir uma grande porcentagem do tempo total de inicialização e execução. Mas o custo de compilar um script em relação ao tempo total de execução diminui para scripts de execução mais longa.

O script que você nomeia na linha de comando nunca é salvo em um arquivo .pyc. Somente módulos carregados por esse script "principal" são salvos dessa maneira.

Bill Karwin
fonte
3
Em muitos casos, é difícil ver a diferença, mas eu tenho um arquivo python específico com mais de 300.000 linhas. (É um monte de cálculos matemáticos gerados por outro script para teste) Leva 37 segundos para compilar e apenas 2 segundos para executar.
Wojtow 15/03/19
54

Vantagens:

Primeiro: ofuscação leve e derrotável.

Segundo: se a compilação resultar em um arquivo significativamente menor, você obterá tempos de carregamento mais rápidos. Bom para a web.

Terceiro: Python pode pular a etapa de compilação. Mais rápido na carga inicial. Bom para a CPU e a web.

Quarto: quanto mais você comentar, menor será o arquivo .pycou .pyoem comparação com o .pyarquivo de origem .

Quinto: é muito menos provável que um usuário final com apenas um arquivo .pycou .pyona mão apresente um bug causado por uma alteração não revertida da qual se esqueceu de falar.

Sexto: se você está buscando um sistema incorporado, obter um arquivo de tamanho menor para incorporar pode representar uma vantagem significativa, e a arquitetura é estável, de modo que a desvantagem, detalhada abaixo, não entra em jogo.

Compilação de nível superior

É útil saber que você pode compilar um arquivo de origem python de nível superior em um .pycarquivo da seguinte maneira:

python -m py_compile myscript.py

Isso remove os comentários. Deixa docstringsintacto. Se você também quiser se livrar do problema docstrings(pense seriamente no motivo de fazer isso), compile dessa maneira ...

python -OO -m py_compile myscript.py

... e você obterá um .pyoarquivo em vez de um .pycarquivo; igualmente distribuível em termos de funcionalidade essencial do código, mas menor pelo tamanho do despojado docstrings(e menos facilmente compreendido para emprego subsequente se tivesse decente docstringsem primeiro lugar). Mas veja a desvantagem três, abaixo.

Note-se que python usa a .pydata do arquivo, se ele estiver presente, para decidir se ele deve executar o .pyarquivo em oposição ao .pycou .pyoarquivo --- então editar o arquivo .py, ea .pycou .pyoé obsoleto e tudo o que os benefícios que você ganhou são perdidas. Você precisa recompilar-lo, a fim de obter o .pycou .pyobenefícios de volta novamente, como eles podem ser.

Desvantagens:

Primeiro: há um "cookie mágico" .pyce os .pyoarquivos que indicam a arquitetura do sistema em que o arquivo python foi compilado. Se você distribuir um desses arquivos em um ambiente de um tipo diferente, ele será interrompido. Se você distribuir o .pycou .pyosem o associado .pypara recompilar ou touchsubstitui o .pycou .pyo, o usuário final também não poderá corrigi-lo.

Segundo: se docstringsfor ignorado com o uso da -OOopção de linha de comando conforme descrito acima, ninguém poderá obter essas informações, o que pode dificultar (ou impossibilitar) o uso do código.

Terceiro: a -OOopção do Python também implementa algumas otimizações conforme a -Oopção da linha de comando; isso pode resultar em alterações na operação. Otimizações conhecidas são:

  • sys.flags.optimize = 1
  • assert as instruções são ignoradas
  • __debug__ = False

Quarto: se você tivesse feito intencionalmente o seu python script executável com algo na ordem de #!/usr/bin/pythonna primeira linha, este é retirado em .pyce .pyoarquivos e que funcionalidade é perdida.

Quinto: um tanto óbvio, mas se você compilar seu código, não apenas o seu uso poderá ser afetado, mas o potencial de outras pessoas aprenderem com seu trabalho é reduzido, muitas vezes severamente.

fyngyrz
fonte
10

Há um aumento de desempenho na execução de python compilado. No entanto, quando você executa um arquivo .py como um módulo importado, o python o compila e armazena, e enquanto o arquivo .py não for alterado, sempre usará a versão compilada.

Com qualquer linguagem interpetada quando o arquivo é usado, o processo é mais ou menos assim:
1. O arquivo é processado pelo interpéter.
2. O arquivo é compilado
3. O código compilado é executado.

obviamente, usando código pré-compilado, você pode eliminar a etapa 2, isso se aplica a python, PHP e outros.

Heres um post interessante no blog que explica as diferenças http://julipedia.blogspot.com/2004/07/compiled-vs-interpreted-languages.html
E aqui está uma entrada que explica o processo de compilação do Python http://effbot.org/zone /python-compile.htm

UnkwnTech
fonte
9

Como já mencionado, você pode obter um aumento no desempenho ao compilar seu código python no bytecode. Isso geralmente é tratado pelo próprio python, apenas para scripts importados.

Outro motivo para compilar seu código python pode ser proteger sua propriedade intelectual de ser copiada e / ou modificada.

Você pode ler mais sobre isso na documentação do Python .

Simon B. Jensen
fonte
2
Com relação à proteção do seu código - a compilação não ajudará muito. Compilar ofusca - mas alguém com o desejo obterá seu código independentemente.
Josh Smeaton
1
@josh isso sempre é possível, se alguém puder acessar a memória ou assistir às instruções da CPU, com tempo suficiente e elas poderão reconstruir seu aplicativo.
UnkwnTech 23/01/09
5
Concordou, no entanto, como Unkwntech disse, que sempre será possível, se a pessoa estiver determinada o suficiente. Mas estou convencido de que será suficiente na maioria das situações, onde normalmente só querem restringir as pessoas de "consertar" o seu código ...
Simon B. Jensen
Os idiomas que são compilados no bytecode geralmente não são tão difíceis de compilar reversamente, a menos que você tome medidas extras para ofuscá-los - apenas compilar geralmente não será suficiente.
EJoshuaS - Restabelecer Monica 12/07/19
7

Certamente há uma diferença de desempenho ao executar um script compilado. Se você executar .pyscripts normais , a máquina o compila toda vez que é executada e isso leva tempo. Nas máquinas modernas, isso é quase imperceptível, mas à medida que o script cresce, pode se tornar mais um problema.

matpie
fonte
7

Algo não abordado é a compilação fonte a fonte . Por exemplo, nuitkaconverte o código Python em C / C ++ e o compila em código binário que é executado diretamente na CPU, em vez do código de código Python que é executado na máquina virtual mais lenta.

Isso pode levar a acelerações significativas, ou permitiria que você trabalhasse com Python enquanto seu ambiente depende do código C / C ++.

user258532
fonte
4

Usamos o código compilado para distribuir aos usuários que não têm acesso ao código fonte. Basicamente, para impedir que programadores inexperientes alterem acidentalmente algo ou corrijam bugs sem nos avisar.

DrBwts
fonte
2

Sim, o desempenho é a principal razão e, até onde eu sei, a única razão.

Se alguns de seus arquivos não estiverem sendo compilados, talvez o Python não consiga gravar no arquivo .pyc, talvez por causa das permissões do diretório ou algo assim. Ou talvez os arquivos não compilados simplesmente nunca estejam sendo carregados ... (scripts / módulos são compilados apenas quando são carregados)

David Z
fonte
1

Iniciantes assumem que o Python é compilado por causa dos arquivos .pyc. O arquivo .pyc é o código de código compilado, que é então interpretado. Portanto, se você já executou o código Python antes e tiver o arquivo .pyc à mão, ele será executado mais rápido na segunda vez, pois não precisará recompilar o bytecode

compilador: um compilador é um pedaço de código que traduz o idioma de alto nível em linguagem de máquina

Intérpretes: os intérpretes também convertem o idioma de alto nível em equivalentes binários legíveis por máquina. Sempre que um intérprete obtém um código de idioma de alto nível a ser executado, ele converte o código em um código intermediário antes de convertê-lo no código da máquina. Cada parte do código é interpretada e, em seguida, executada separadamente em uma sequência. Se um erro for encontrado em uma parte do código, interromperá a interpretação do código sem traduzir o próximo conjunto de códigos.

Fontes: http://www.toptal.com/python/why-are-there-so-many-pythons http://www.engineersgarage.com/contribution/difference-between-compiler-and-interpreter

Principiante
fonte
9
Sua definição de "compilador" está incorreta. Nunca foi necessário um compilador para compilar com o código da máquina. Um compilador é apenas um tradutor de um idioma para outro. É por isso que dizemos que o Python "compila" no bytecode, o Coffeescript "compila" no Javascript e assim por diante.
Ricky Stewart