Pourquoi compiler du code Python?

241

Pourquoi voudriez-vous compiler un script Python? Vous pouvez les exécuter directement à partir du fichier .py et cela fonctionne très bien, donc y a-t-il un avantage de performance ou quelque chose?

Je remarque également que certains fichiers de mon application sont compilés en .pyc tandis que d'autres ne le sont pas, pourquoi?

ryeguy
la source
Vous pouvez également noter que, y compris le démarrage plus rapide de votre application, vous gagnez également en sécurité, si vous ne pouvez pas partager votre code s'il s'agit d'un secret d'entreprise.
Please_Dont_Bully_Me_SO_Lords
@PSyLoCKe Vous vraiment, vraiment pas. Le bytecode Python est vraiment lisible, car le compilateur n'a pas besoin de le masquer pour l'optimiser. (Pas que ça l'optimise beaucoup ...)
wizzwizz4
1
La raison pour laquelle certains fichiers sont compilés automatiquement est qu'ils sont importés; par exemple, si vous utilisez import mylib.py, Python se compilera mylib.pypour que les futures importinstructions s'exécutent un peu plus rapidement. Si vous modifiez plus tard mylib.py, il sera recompilé la prochaine fois qu'il sera importé (Python utilise la date du fichier pour voir que cela se produit.)
fyngyrz

Réponses:

270

Il est compilé en bytecode qui peut être utilisé beaucoup, beaucoup, beaucoup plus rapidement.

La raison pour laquelle certains fichiers ne sont pas compilés est que le script principal avec lequel vous invoquez python main.pyest recompilé à chaque fois que vous exécutez le script. Tous les scripts importés seront compilés et stockés sur le disque.

Ajout important de Ben Blank :

Il convient de noter que lors de l'exécution d'un script compilé , le temps de démarrage est plus rapide (car il n'a pas besoin d'être compilé), il ne s'exécute pas plus rapidement.

Georg Schölly
la source
260
Il convient de noter que lors de l'exécution d'un script compilé , le temps de démarrage est plus rapide (car il n'a pas besoin d'être compilé), il ne s'exécute pas plus rapidement.
Ben Blank
24
Une idée fausse commune. Merci d'avoir partagé.
matpie
1
En plus de ne pas nécessiter de compilation, le fichier .pyc est presque toujours plus petit. Surtout si vous commentez beaucoup. L'un des miens est 28419 en .py, mais seulement 17879 en .pyc - donc le temps de chargement est également meilleur. Enfin, vous pouvez précompiler les scripts de niveau supérieur de cette façon: python -m compileall myscript.py
fyngyrz
1
Y a-t-il une différence dans la consommation de mémoire? Je teste Python sur des appareils intégrés basés sur des processeurs mips avec seulement 64 Mo de RAM, donc y a-t-il un avantage à utiliser la mémoire lors du démarrage d'une version compilée du script python?
valentt
1
@valentt: Probablement pas. Je ne sais pas grand chose sur les internes de Python, mais je ne pense pas que l'analyse du bytecode demande beaucoup de mémoire en Python. Je ne peux pas penser à quelque chose qui a besoin de beaucoup de mémoire pour se souvenir d'un état.
Georg Schölly
80

Le fichier .pyc est Python qui a déjà été compilé en octet-code. Python exécute automatiquement un fichier .pyc s'il en trouve un portant le même nom qu'un fichier .py que vous invoquez.

"An Introduction to Python" dit ceci à propos des fichiers Python compilés:

Un programme ne s'exécute pas plus rapidement lorsqu'il est lu à partir d'un fichier '.pyc' ou '.pyo' que lorsqu'il est lu à partir d'un fichier '.py'; la seule chose qui est plus rapide avec les fichiers '.pyc' ou '.pyo' est la vitesse à laquelle ils sont chargés.

L'avantage de l'exécution d'un fichier .pyc est que Python n'a pas à supporter la surcharge de sa compilation avant de l'exécuter. Étant donné que Python compilerait en octet-code avant d'exécuter un fichier .py de toute façon, il ne devrait y avoir aucune amélioration des performances en dehors de cela.

Quelle amélioration pouvez-vous obtenir en utilisant des fichiers .pyc compilés? Cela dépend de ce que fait le script. Pour un script très bref qui affiche simplement "Hello World", la compilation peut constituer un pourcentage important du temps total de démarrage et d'exécution. Mais le coût de compilation d'un script par rapport à la durée totale d'exécution diminue pour les scripts plus longs.

Le script que vous nommez sur la ligne de commande n'est jamais enregistré dans un fichier .pyc. Seuls les modules chargés par ce script "principal" sont enregistrés de cette manière.

Bill Karwin
la source
3
Dans de nombreux cas, il est difficile de voir une différence, mais j'ai un fichier python particulier avec plus de 300 000 lignes. (C'est un tas de calculs mathématiques générés par un autre script pour les tests) Il faut 37 secondes pour compiler et seulement 2 secondes pour exécuter.
wojtow
54

Avantages:

Premièrement: une obscurcissement léger et vaincu.

Deuxièmement: si la compilation aboutit à un fichier beaucoup plus petit, vous obtiendrez des temps de chargement plus rapides. Sympa pour le web.

Troisièmement: Python peut ignorer l'étape de compilation. Plus rapide à charge initiale. Sympa pour le CPU et le web.

Quatrièmement: plus vous commentez, plus le fichier .pycou .pyosera petit par rapport au .pyfichier source .

Cinquièmement: un utilisateur final avec seulement un .pycou un .pyofichier en main est beaucoup moins susceptible de vous présenter un bogue causé par un changement non annulé dont il a oublié de vous parler.

Sixièmement: si vous visez un système embarqué, l'obtention d'un fichier de plus petite taille à incorporer peut représenter un avantage significatif, et l'architecture est stable, donc un inconvénient, détaillé ci-dessous, n'entre pas en jeu.

Compilation de haut niveau

Il est utile de savoir que vous pouvez compiler un fichier source python de niveau supérieur dans un .pycfichier de cette façon:

python -m py_compile myscript.py

Cela supprime les commentaires. Il laisse docstringsintact. Si vous souhaitez vous en débarrasser docstringségalement (vous voudrez peut-être réfléchir sérieusement à la raison pour laquelle vous faites cela), compilez de cette façon à la place ...

python -OO -m py_compile myscript.py

... et vous obtiendrez un .pyofichier au lieu d'un .pycfichier; également distribuable en termes de fonctionnalités essentielles du code, mais plus petit par la taille du dépouillé docstrings(et moins facile à comprendre pour un emploi ultérieur s'il avait été décent docstringsen premier lieu). Mais voir l'inconvénient trois, ci-dessous.

Notez que python utilise la .pydate du fichier, si elle est présente, pour décider s'il doit exécuter le .pyfichier par opposition au fichier .pycou .pyo--- alors modifiez votre fichier .py, et le .pycou .pyoest obsolète et tous les avantages que vous avez gagnés sont perdus. Vous devez le recompiler afin de récupérer à nouveau le .pycou les .pyoavantages, tels qu'ils peuvent être.

Désavantages:

Premièrement: il y a un "cookie magique" dans .pycet des .pyofichiers qui indique l'architecture système dans laquelle le fichier python a été compilé. Si vous distribuez l'un de ces fichiers dans un environnement d'un type différent, il se cassera. Si vous distribuez le .pycou .pyosans l'associé .pyà recompiler ou touchsi cela remplace le .pycou .pyo, l'utilisateur final ne peut pas le réparer non plus.

Deuxièmement: si vous docstringsignorez l'utilisation de l' -OOoption de ligne de commande décrite ci-dessus, personne ne pourra accéder à ces informations, ce qui peut rendre l'utilisation du code plus difficile (ou impossible).

Troisièmement: l' -OOoption de Python implémente également certaines optimisations selon l' -Ooption de ligne de commande; cela peut entraîner des changements de fonctionnement. Les optimisations connues sont:

  • sys.flags.optimize = 1
  • assert les instructions sont ignorées
  • __debug__ = Faux

Quatrièmement: si vous aviez intentionnellement rendu votre script python exécutable avec quelque chose dans l'ordre de #!/usr/bin/pythonla première ligne, cela est supprimé dans .pycet les .pyofichiers et cette fonctionnalité est perdue.

Cinquièmement: quelque peu évident, mais si vous compilez votre code, non seulement son utilisation peut être affectée, mais le potentiel des autres à apprendre de votre travail est réduit, souvent sévèrement.

fyngyrz
la source
10

Il y a une augmentation des performances lors de l'exécution de python compilé. Cependant, lorsque vous exécutez un fichier .py en tant que module importé, python le compilera et le stockera, et tant que le fichier .py ne changera pas, il utilisera toujours la version compilée.

Avec n'importe quelle langue interpétée lorsque le fichier est utilisé, le processus ressemble à ceci:
1. Le fichier est traité par l'interpètre.
2. Le fichier est compilé
3. Le code compilé est exécuté.

Évidemment, en utilisant du code précompilé, vous pouvez éliminer l'étape 2, cela s'applique à Python, PHP et autres.

Voici un article de blog intéressant expliquant les différences http://julipedia.blogspot.com/2004/07/compiled-vs-interpreted-languages.html
Et voici une entrée qui explique le processus de compilation Python http://effbot.org/zone /python-compile.htm

UnkwnTech
la source
9

Comme déjà mentionné, vous pouvez obtenir une augmentation des performances en compilant votre code python en bytecode. Ceci est généralement géré par python lui-même, pour les scripts importés uniquement.

Une autre raison pour laquelle vous voudrez peut-être compiler votre code python pourrait être de protéger votre propriété intellectuelle contre la copie et / ou la modification.

Vous pouvez en savoir plus à ce sujet dans la documentation Python .

Simon B. Jensen
la source
2
En ce qui concerne la protection de votre code, la compilation n'aidera pas beaucoup. Compiler obscurcit - mais quelqu'un avec le désir obtiendra quand même votre code.
Josh Smeaton
1
@josh c'est toujours possible, si l'on peut accéder à la mémoire ou regarder les instructions du processeur, avec assez de temps et ils pourront reconstruire votre application.
UnkwnTech
5
D'accord, cependant, comme l'a dit Unkwntech, cela sera toujours possible, si la personne est suffisamment déterminée. Mais je suis convaincu que cela suffira dans la plupart des situations, où vous voulez généralement empêcher les gens de "réparer" votre code ...
Simon B. Jensen
Les langues qui sont compilées en bytecode ne sont généralement pas si difficiles à inverser la compilation, sauf si vous prenez des mesures supplémentaires pour les obscurcir - la simple compilation ne sera généralement pas suffisante.
EJoshuaS
7

Il y a certainement une différence de performances lors de l'exécution d'un script compilé. Si vous exécutez des .pyscripts normaux , la machine le compile à chaque exécution et cela prend du temps. Sur les machines modernes, cela est à peine perceptible, mais à mesure que le script se développe, il peut devenir plus problématique.

matpie
la source
7

Quelque chose qui n'est pas abordé est la compilation de source à source . Par exemple,nuitka traduit le code Python en C / C ++, et le compile en code binaire qui s'exécute directement sur le CPU, au lieu du bytecode Python qui s'exécute sur la machine virtuelle plus lente.

Cela peut entraîner des accélérations importantes ou vous permettre de travailler avec Python alors que votre environnement dépend du code C / C ++.

user258532
la source
4

Nous utilisons du code compilé pour distribuer aux utilisateurs qui n'ont pas accès au code source. Fondamentalement, pour empêcher les programmeurs inexpérimentés de modifier accidentellement quelque chose ou de corriger des bogues sans nous le dire.

DrBwts
la source
2

Oui, la performance est la principale raison et, pour autant que je sache, la seule raison.

Si certains de vos fichiers ne sont pas compilés, Python n'est peut-être pas en mesure d'écrire dans le fichier .pyc, peut-être à cause des autorisations de répertoire ou quelque chose. Ou peut-être que les fichiers non compilés ne sont jamais chargés ... (les scripts / modules ne sont compilés que lorsqu'ils sont chargés pour la première fois)

David Z
la source
1

Les débutants supposent que Python est compilé à cause des fichiers .pyc. Le fichier .pyc est le bytecode compilé, qui est ensuite interprété. Donc, si vous avez déjà exécuté votre code Python et que vous avez le fichier .pyc à portée de main, il s'exécutera plus rapidement la deuxième fois, car il n'a pas à recompiler le bytecode

compilateur: un compilateur est un morceau de code qui traduit le langage de haut niveau en langage machine

Interprètes: Les interprètes convertissent également le langage de haut niveau en équivalents binaires lisibles par machine. Chaque fois qu'un interprète obtient un code de langue de haut niveau à exécuter, il convertit le code en code intermédiaire avant de le convertir en code machine. Chaque partie du code est interprétée puis exécutée séparément dans une séquence et une erreur est trouvée dans une partie du code, elle arrêtera l'interprétation du code sans traduire l'ensemble suivant des codes.

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

Débutant
la source
9
Votre définition de «compilateur» est incorrecte. Un compilateur n'a jamais été sous pour compiler en code machine. Un compilateur est simplement un traducteur d'une langue à une autre. C'est pourquoi nous disons que Python "compile" en bytecode, Coffeescript "compile" en Javascript, et ainsi de suite.
Ricky Stewart