Si Python est interprété, que sont les fichiers .pyc?

1084

On m'a donné à comprendre que Python est un langage interprété ...
Cependant, quand je regarde mon code source Python, je vois des .pycfichiers, que Windows identifie comme "Fichiers Python compilés".

D'où viennent-ils?

froadie
la source
3
Voir stackoverflow.com/questions/11433579/… pour une justification. En un mot: la vitesse.
user7610
Cela signifie-t-il que même python a cette fonction "Écrire une fois, exécuter n'importe où", tout comme Java.?
Mrak Vladar
2
@MrakVladar Même Java est "Écrivez une fois, exécutez n'importe où [que vous avez une JVM]". Python n'est pas différent; il est "exécuté partout où vous avez une machine virtuelle Python". La grande différence est que la plupart des implémentations Python combinent le compilateur et l'interpréteur en un seul exécutable, plutôt que de les séparer comme javaet javac.
chepner

Réponses:

661

Ils contiennent du code octet , ce à quoi l'interpréteur Python compile la source. Ce code est ensuite exécuté par la machine virtuelle de Python.

La documentation de Python explique la définition comme ceci:

Python est un langage interprété, par opposition à un langage compilé, bien que la distinction puisse être floue en raison de la présence du compilateur de bytecode. Cela signifie que les fichiers source peuvent être exécutés directement sans créer explicitement un exécutable qui est ensuite exécuté.

se détendre
la source
10
Intéressant, merci. Python est-il donc considéré comme un langage purement interprété?
froadie
194
@froadie: une langue n'est pas "interprétée" ou "compilée" en tant que telle. Une implémentation spécifique peut être un interpréteur ou un compilateur (ou un hybride ou un compilateur JIT).
Joachim Sauer
30
Un test de «compilé»: est-il compilé selon les instructions réelles de la machine? Le bytecode Python n'est pas une instruction machine, pas plus que les instructions Java 'JVM', donc aucun de ces langages n'est compilé par cette définition. Mais les deux sont «compilés» en un code intermédiaire de «machine abstraite», et les deux sont bien plus rapides que l'exécution du programme en interprétant plus ou moins directement le code source (ce que fait BASIC à l'ancienne).
greggo
20
Pour être pédant, «compilé» signifie «traduit». Python est ensuite compilé en un bytecode. AFAIK, seul Bash est vraiment interprété, tous les autres langages "interprétés" populaires sont tous compilés en un bytecode.
bfontaine
13
En fait, ce sont des instructions machine, mais pas des instructions machine natives pour le CPU physique de l'hôte. D'où la raison pour laquelle nous l'appelons VM? Comme l'espéranto pour le langage d'assemblage vraiment. De nos jours, nous avons même du code natif pour les CPU fictifs (mais toujours émulés) (l'effort de Mojang pour intéresser les enfants). Rexx a été (ou pourrait être) véritablement interprété, et BAT et CMD (et DCL) sont interprétés.
mckenzm
995

On m'a donné à comprendre que Python est un langage interprété ...

Ce mème populaire est incorrect, ou plutôt construit sur une mauvaise compréhension des niveaux de langage (naturel): une erreur similaire serait de dire "la Bible est un livre relié". Permettez-moi d'expliquer cette comparaison ...

"La Bible" est "un livre" dans le sens d'être une classe de livres (réels, physiques identifiés comme); les livres identifiés comme "copies de la Bible" sont censés avoir quelque chose de fondamental en commun (le contenu, même si ceux-ci peuvent être dans différentes langues, avec des traductions acceptables différentes, des niveaux de notes de bas de page et d'autres annotations) - cependant, ces livres sont parfaitement bien autorisé à différer dans une myriade d'aspects qui ne sont pas considérés comme fondamentaux - type de reliure, couleur de la reliure, police (s) utilisée (s) dans l'impression, illustrations le cas échéant, larges marges inscriptibles ou non, nombres et types de signets intégrés , et ainsi de suite.

Il est tout à fait possible qu'une impression typique de la Bible soit en effet sous reliure cartonnée - après tout, c'est un livre qui est généralement destiné à être lu à plusieurs reprises, mis en signet à plusieurs endroits, feuilleté à la recherche de pointeurs de chapitre et de versets donnés , etc, etc, et une bonne reliure cartonnée peut faire durer une copie donnée plus longtemps dans une telle utilisation. Cependant, ce sont des questions banales (pratiques) qui ne peuvent pas être utilisées pour déterminer si un objet de livre réel donné est une copie de la Bible ou non: des impressions de poche sont parfaitement possibles!

De même, Python est "un langage" dans le sens de définir une classe d' implémentations de langage qui doivent toutes être similaires à certains égards fondamentaux (syntaxe, la plupart des sémantiques sauf les parties de celles où elles sont explicitement autorisées à différer) mais sont entièrement autorisées pour différer dans à peu près tous les détails de "l'implémentation" - y compris la façon dont ils traitent les fichiers source qui leur sont fournis, s'ils compilent les sources dans des formulaires de niveau inférieur (et, si oui, quel formulaire - et s'ils enregistrent ces formulaires compilés, sur disque ou ailleurs), comment ils exécutent lesdits formulaires, etc.

L'implémentation classique, CPython, est souvent appelée simplement "Python" pour faire court - mais ce n'est qu'une des nombreuses implémentations de qualité de production, côte à côte avec IronPython de Microsoft (qui compile en codes CLR, c'est-à-dire ".NET"), Jython (qui se compile en codes JVM), PyPy (qui est écrit en Python lui-même et peut se compiler dans une grande variété de formes "back-end", y compris le langage machine généré "juste à temps"). Ce sont tous des Python (== "implémentations du langage Python") tout comme de nombreux objets de livres superficiellement différents peuvent tous être des Bibles (== "copies de La Bible").

Si vous êtes spécifiquement intéressé par CPython: il compile les fichiers source dans un formulaire de niveau inférieur spécifique à Python (connu sous le nom de "bytecode"), le fait automatiquement en cas de besoin (lorsqu'il n'y a pas de fichier de bytecode correspondant à un fichier source, ou le fichier de bytecode est plus ancien que la source ou compilé par une version différente de Python), enregistre généralement les fichiers de bytecode sur le disque (pour éviter de les recompiler à l'avenir). OTOH IronPython compilera généralement en codes CLR (en les enregistrant sur disque ou non, selon) et en Jython en codes JVM (en les enregistrant sur disque ou non - il utilisera l' .classextension s'il les enregistre).

Ces formulaires de niveau inférieur sont ensuite exécutés par des "machines virtuelles" appropriées également appelées "interprètes" - la machine virtuelle CPython, le runtime .Net, la machine virtuelle Java (alias JVM), selon le cas.

Donc, dans ce sens (que font les implémentations typiques), Python est un "langage interprété" si et seulement si C # et Java le sont: tous ont une stratégie d'implémentation typique de produire d'abord du bytecode, puis de l'exécuter via une VM / interprète .

Il est plus probable que l'accent soit mis sur la «lourdeur», la lenteur et la haute cérémonie du processus de compilation. CPython est conçu pour compiler aussi rapidement que possible, aussi léger que possible, avec aussi peu de cérémonie que possible - le compilateur effectue très peu de vérification et d'optimisation des erreurs, de sorte qu'il peut fonctionner rapidement et dans de petites quantités de mémoire, ce qui à son tour le permet être exécuté automatiquement et de manière transparente chaque fois que cela est nécessaire, sans que l'utilisateur ait même besoin de savoir qu'une compilation est en cours, la plupart du temps. Java et C # acceptent généralement plus de travail pendant la compilation (et n'effectuent donc pas de compilation automatique) afin de vérifier les erreurs plus en profondeur et d'effectuer plus d'optimisations. C'est un continuum d'échelles de gris, pas une situation en noir ou blanc,

Alex Martelli
la source
2
Belle réponse. Juste une petite correction au dernier paragraphe: Python est conçu pour compiler aussi vite que possible (etc.). Cette fois, c'est vraiment la langue, avec son manque de système de type statique et tout ça. Lorsque les gens parlent de langues "interprétées", ils signifient généralement des langues "dynamiques".
Elazar
2
@Elazar, en fait, d'autres implémentations de Python, telles que PyPy, qui ne sont pas pressées de compiler, parviennent à faire l'analyse plus approfondie requise par le manque de typage statique et produisent une compilation juste à temps pour coder la machine (accélérant ainsi plusieurs fois des programmes de longue durée).
Alex Martelli
Où se situe Cython ici? Considérez-vous qu'il s'agit d'un langage différent ou s'agit-il d'une implémentation Python? En outre, ce mème de "interprété" vs compilé n'est-il peut-être qu'une confusion terminologique parce que la machine virtuelle de Python est souvent appelée son "interprète"? Il serait tout aussi valable d'appeler la JVM ou les interpréteurs d'exécution .NET. Ils interprètent tous deux principalement le bytecode en code machine JIT (avec quelques exceptions d'optimisation de la mise en cache)
Davos
181

Il n'y a pas de langage interprété. Qu'un interprète ou un compilateur soit utilisé est purement un trait de l' implémentation et n'a absolument rien à voir avec le langage.

Chaque langue peut être implémentée par un interprète ou un compilateur. La grande majorité des langues ont au moins une implémentation de chaque type. (Par exemple, il existe des interprètes pour C et C ++ et il existe des compilateurs pour JavaScript, PHP, Perl, Python et Ruby.) En outre, la majorité des implémentations de langage moderne combinent en fait à la fois un interprète et un compilateur (ou même plusieurs compilateurs).

Un langage n'est qu'un ensemble de règles mathématiques abstraites. Un interprète est l'une des nombreuses stratégies de mise en œuvre concrètes d'une langue. Ces deux-là vivent à des niveaux d'abstraction complètement différents. Si l'anglais était une langue dactylographiée, le terme «langue interprétée» serait une erreur de type. La déclaration "Python est un langage interprété" n'est pas seulement fausse (car être fausse impliquerait que la déclaration a même un sens, même si elle est erronée), elle n'a tout simplement aucun sens , car un langage ne peut jamais être défini comme "interprété."

En particulier, si vous regardez les implémentations Python actuellement existantes, ce sont les stratégies d'implémentation qu'elles utilisent:

  • IronPython: compile en arborescences DLR que le DLR compile ensuite en bytecode CIL. Ce qui arrive au bytecode CIL dépend du CLI VES sur lequel vous exécutez, mais Microsoft .NET, GNU Portable.NET et Novell Mono finiront par le compiler en code machine natif.
  • Jython: interprète le code source Python jusqu'à ce qu'il identifie les chemins de code actif, qu'il compile ensuite en bytecode JVML. Ce qui arrive au bytecode JVML dépend de la machine virtuelle Java sur laquelle vous exécutez. Maxine le compilera directement en code natif non optimisé jusqu'à ce qu'il identifie les chemins de code actif, qu'il recompile ensuite en code natif optimisé. HotSpot interprètera d'abord le bytecode JVML, puis finira par compiler les chemins de code chaud en code machine optimisé.
  • PyPy: compile en PyPy bytecode, qui est ensuite interprété par la machine virtuelle PyPy jusqu'à ce qu'il identifie les chemins de code à chaud qu'il compile ensuite en code natif, JVML bytecode ou CIL bytecode selon la plateforme sur laquelle vous exécutez.
  • CPython: compile en CPython bytecode qu'il interprète ensuite.
  • Stackless Python: compile en CPython bytecode qu'il interprète ensuite.
  • Hirondelle à vide: compile en CPython bytecode qu'il interprète ensuite jusqu'à ce qu'il identifie les chemins de code à chaud qu'il compile ensuite en LLVM IR que le compilateur LLVM compile ensuite en code machine natif.
  • Cython: compile le code Python en code C portable, qui est ensuite compilé avec un compilateur C standard
  • Nuitka: compile le code Python en code C ++ dépendant de la machine, qui est ensuite compilé avec un compilateur C standard

Vous remarquerez peut-être que chacune des implémentations de cette liste (ainsi que d'autres que je n'ai pas mentionnées, comme tinypy, Shedskin ou Psyco) a un compilateur. En fait, pour autant que je sache, il n'y a actuellement aucune implémentation Python purement interprétée, aucune implémentation de ce type n'est prévue et il n'y a jamais eu une telle implémentation.

Non seulement le terme "langage interprété" n'a pas de sens, même si vous l'interprétez comme signifiant "langage avec implémentation interprétée", ce n'est clairement pas vrai. Celui qui vous a dit cela ne sait évidemment pas de quoi il parle.

En particulier, les .pycfichiers que vous voyez sont des fichiers de bytecode mis en cache produits par CPython, Stackless Python ou Unladen Swallow.

Jörg W Mittag
la source
6
Les bases de la vieille école telles que MSBASIC n'avaient pas de forme intermédiaire. Le programme a été interprété directement à partir du formulaire source (ou de la source proche, un formulaire dans lequel les mots clés étaient représentés par des jetons de 1 octet et les numéros de ligne par des entiers binaires de 2 octets, mais le reste était simplement ASCII). Donc, en fait, un «goto» prendrait différentes quantités de temps selon le nombre de lignes source qu'il devait rechercher en recherchant la destination correspondante. Des expressions comme a * b-2 * cos (x) ont été effectivement ré-analysées à chaque exécution.
greggo
4
@greggo: Et si vous voulez aller encore plus à l'ancienne, la version originale de BASIC était un compilateur de code natif. Cela devrait prouver à quel point la notion de langage "compilé" ou "interprété" est ridicule.
Jörg W Mittag
Merci d'avoir expliqué comment les différents compilateurs / interprètes python se comportent. Je me demande s'il existe de bons compilateurs Python qui génèrent encore du C ou du JavaScript efficace. Cela semble très faisable, peut-être pas pour la consommation de masse, mais pour un sous-ensemble raisonnable de Python au moins. Je me demande aussi ce qu'est Cython.
personal_cloud
Cython a été mentionné dans SciPy 2009, mais je peux vous pardonner de ne pas le savoir en 2010 (ici, je suis en 2017 seulement en train de l'apprendre). Nous devons quand même trouver un exemple JavaScript ... Jython n'a aucun sens pour moi (Java n'était-il pas déjà mort en 2009? Eh bien hmm, peut-être pas ... Le boost C ++ n'était pas si bon à l'époque)
personal_cloud
1
@personal_cloud: Je ne suis pas tout à fait à votre écoute. Oui, bien sûr, je connais Cython, mais qu'est-ce que cela a à voir avec quoi que ce soit? Ce n'est pas une implémentation de Python, c'est un langage complètement différent. De plus, il n'est vraiment pas difficile de trouver un exemple JavaScript, en fait, toutes les implémentations JavaScript courantes existantes ont des compilateurs. Enfin, Jython est une implémentation de Python comme toute autre implémentation de Python. Et c'est une implémentation d'un langage sur la plate-forme Java, comme toute autre implémentation de langage sur la plate-forme Java.
Jörg W Mittag
61

Ceux-ci sont créés par l'interpréteur Python lorsqu'un .pyfichier est importé, et ils contiennent le "bytecode compilé" du module / programme importé, l'idée étant que la "traduction" du code source en bytecode (qui ne doit être effectuée qu'une seule fois) peut être ignoré sur les imports suivants s'il .pycest plus récent que le .pyfichier correspondant , accélérant ainsi un peu le démarrage. Mais c'est toujours interprété.

Tim Pietzcker
la source
10
Vrai. Sauf que de nombreuses bibliothèques Python de base sont écrites en C. Ainsi, certaines parties de python s'exécutent interprétées, une partie s'exécute en C. Vous pouvez faire de même pour vos propres bits de code sensibles aux performances.
bwawok
44

Pour accélérer le chargement des modules, Python met en cache le contenu compilé des modules en .pyc.

CPython compile son code source en "code d'octet", et pour des raisons de performances, il met en cache ce code d'octet sur le système de fichiers chaque fois que le fichier source change. Cela accélère le chargement des modules Python car la phase de compilation peut être contournée. Lorsque votre fichier source est foo.py, CPython met en cache le code d'octet dans un fichier foo.pyc juste à côté de la source.

En python3, la machinerie d'importation de Python est étendue pour écrire et rechercher des fichiers de cache de code octet dans un seul répertoire à l'intérieur de chaque répertoire de package Python. Ce répertoire sera appelé __pycache__.

Voici un organigramme décrivant comment les modules sont chargés:

entrez la description de l'image ici

Pour plus d'informations:

ref: PEP3147
ref: Fichiers Python "compilés"

hxysayhi
la source
38

C'EST POUR LES DÉBUTANTS,

Python compile automatiquement votre script en code compilé, appelé code d'octets, avant de l'exécuter.

L'exécution d'un script n'est pas considérée comme une importation et aucun .pyc ne sera créé.

Par exemple, si vous avez un fichier de script abc.py qui importe un autre module xyz.py , lorsque vous exécutez abc.py , xyz.pyc sera créé puisque xyz est importé, mais aucun fichier abc.pyc ne sera créé depuis abc. py n'est pas importé.

Si vous devez créer un fichier .pyc pour un module qui n'est pas importé, vous pouvez utiliser les modules py_compileet compileall.

Le py_compilemodule peut compiler manuellement n'importe quel module. Une façon consiste à utiliser la py_compile.compilefonction dans ce module de manière interactive:

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

Cela écrira le .pyc au même emplacement que abc.py (vous pouvez le remplacer avec le paramètre facultatif cfile).

Vous pouvez également compiler automatiquement tous les fichiers d'un ou de plusieurs répertoires à l'aide du module compileall.

python -m compileall

Si le nom du répertoire (le répertoire courant dans cet exemple) est omis, le module compile tout ce qui se trouve sur sys.path

MAX
la source
6
et quel est l'avantage de compiler pour obtenir l'abc.py?
Saher Ahwal
@SaherAhwal Un avantage auquel je peux penser est la vérification de la syntaxe.
Yi Bao
20

Python (au moins l'implémentation la plus courante de celui-ci) suit un modèle de compilation de la source d'origine en codes d'octets, puis d'interprétation des codes d'octets sur une machine virtuelle. Cela signifie (là encore, l'implémentation la plus courante) n'est ni un pur interprète ni un pur compilateur.

L'autre côté de ceci est, cependant, que le processus de compilation est principalement caché - les fichiers .pyc sont fondamentalement traités comme un cache; ils accélèrent les choses, mais vous n'avez normalement pas besoin d'en être conscients. Il les invalide automatiquement et les recharge (recompile le code source) si nécessaire en fonction des horodatages du fichier.

La seule fois où j'ai vu un problème avec cela, c'est quand un fichier de bytecode compilé a en quelque sorte un horodatage dans le futur, ce qui signifie qu'il a toujours l'air plus récent que le fichier source. Comme il avait l'air plus récent, le fichier source n'a jamais été recompilé, donc peu importe les modifications que vous avez apportées, il a été ignoré ...

Jerry Coffin
la source
12

Le fichier * .py de Python est juste un fichier texte dans lequel vous écrivez quelques lignes de code. Lorsque vous essayez d'exécuter ce fichier en utilisant, dites "python filename.py"

Cette commande appelle Python Virtual Machine. La machine virtuelle Python a 2 composants: "compilateur" et "interprète". L'interpréteur ne peut pas lire directement le texte dans le fichier * .py, donc ce texte est d'abord converti en un code d'octet qui est destiné au PVM (pas matériel mais PVM) . PVM exécute ce code d'octet. * Le fichier .pyc est également généré, dans le cadre de son exécution, qui effectue votre opération d'importation sur le fichier dans le shell ou dans un autre fichier.

Si ce fichier * .pyc est déjà généré, chaque fois que vous exécutez / exécutez votre fichier * .py, le système charge directement votre fichier * .pyc qui ne nécessite aucune compilation (cela vous fera économiser des cycles machine du processeur).

Une fois le fichier * .pyc généré, il n'est plus nécessaire d'avoir le fichier * .py, sauf si vous le modifiez.

Vishal Mopari
la source
7

Le code Python passe par 2 étapes. La première étape compile le code dans des fichiers .pyc qui est en fait un bytecode. Ensuite, ce fichier .pyc (bytecode) est interprété à l'aide de l'interpréteur CPython. Veuillez vous référer à ce lien. Ici, le processus de compilation et d'exécution de code est expliqué en termes simples.

Tango
la source