1231 votes

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

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

Où est-ce qu'ils entrent en jeu ?

5 votes

Voir stackoverflow.com/questions/11433579/ pour une justification. En un mot : la rapidité.

3 votes

0 votes

1086voto

Alex Martelli Points 330805

J'ai été amené à 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 à couverture rigide". Laissez-moi expliquer cette comparaison...

"La Bible" est "un livre" dans le sens d'être un classe de (véritables objets physiques identifiés comme) livres ; les livres identifiés comme "copies de la Bible" sont censés avoir quelque chose de fondamental en commun (le contenu, bien que même celui-ci puisse être dans des langues différentes, avec des traductions acceptables, des niveaux différents de notes de bas de page et d'autres annotations) - cependant, ces livres sont parfaitement autorisés à différer dans une myriade d'aspects qui ne sont pas du ressort de l'État. pas considérés comme fondamentaux : type de reliure, couleur de la reliure, police(s) de caractères utilisée(s) dans l'impression, illustrations éventuelles, marges d'écriture larges ou non, nombre et types de signets intégrés, et ainsi de suite.

Il est tout à fait possible qu'un typique Une impression de la Bible serait en effet reliée avec une couverture rigide -- après tout, c'est un livre qui est typiquement destiné à être lu et relu, marqué de plusieurs signets, feuilleté à la recherche d'indications sur les chapitres et les versets, etc, etc, et une bonne reliure rigide peut permettre à un exemplaire donné de durer plus longtemps sous cette utilisation. Cependant, il s'agit là de questions banales (pratiques) qui ne peuvent pas être utilisées pour déterminer si un objet livresque donné est une copie de la Bible ou non : des impressions de poche sont parfaitement possibles !

De la même manière, Python est "un langage" dans le sens où il définit une classe de langue mises en œuvre qui doivent tous être similaires à certains égards fondamentaux (syntaxe, la plupart des sémantiques, à l'exception des parties où ils sont explicitement autorisés à différer), mais qui sont pleinement autorisés à différer dans presque tous les détails de "mise en œuvre" -- y compris la façon dont ils traitent les fichiers sources qui leur sont donnés, s'ils compilent les sources vers des formes de niveau inférieur (et, si oui, quelle forme -- et s'ils sauvegardent ces formes compilées, sur le disque ou ailleurs), comment ils exécutent lesdites formes, et ainsi de suite.

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

Si vous êtes intéressé par CPython en particulier : il compile les fichiers sources dans une forme de niveau inférieur spécifique à Python (connue sous le nom de "bytecode"), le fait automatiquement lorsque cela est nécessaire (lorsqu'il n'y a pas de fichier bytecode correspondant à un fichier source, ou que le fichier bytecode est plus ancien que la source ou compilé par une version différente de Python), sauvegarde généralement les fichiers bytecode sur le disque (pour éviter de les recompiler à l'avenir). En revanche, IronPython compile généralement les codes CLR (en les sauvegardant sur le disque ou non, selon le cas) et Jython les codes JVM (en les sauvegardant sur le disque ou non - il utilisera la commande .class extension si elle les sauve).

Ces formes de niveau inférieur sont ensuite exécutées par les "machines virtuelles" appropriées, également appelées "interpréteurs" - la VM CPython, le runtime .Net, la VM Java (alias JVM), selon le cas.

Ainsi, dans ce sens (ce 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 consistant à produire d'abord le bytecode, puis à l'exécuter via une VM/interprète.

Il est plus probable que l'accent soit mis sur la lourdeur, la lenteur et la lourdeur du processus de compilation. CPython est conçu pour compiler aussi rapidement que possible, aussi légèrement que possible, avec aussi peu de cérémonie que possible -- le compilateur fait très peu de contrôle d'erreurs et d'optimisation, de sorte qu'il peut fonctionner rapidement et dans de petites quantités de mémoire, ce qui lui permet d'être exécuté automatiquement et de manière transparente chaque fois que nécessaire, sans que l'utilisateur ait besoin d'être conscient 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 de manière plus approfondie et d'effectuer plus d'optimisations. Il s'agit d'un continuum d'échelles de gris, et non d'une situation en noir ou blanc, et il serait tout à fait arbitraire de fixer un seuil à un niveau donné et de dire que ce n'est qu'au-dessus de ce niveau que l'on peut parler de "compilation" !-)

4 votes

Belle réponse. Juste une petite correction au dernier paragraphe : Python est conçu pour compiler le plus rapidement possible (etc.). Cette fois, c'est vraiment le langage, avec son absence de système de types statique et autres. Quand les gens parlent de langages "interprétés", ils veulent généralement dire des langages "dynamiques".

3 votes

@Elazar, en fait, d'autres implémentations de Python, comme PyPy, qui ne sont pas pressées de compiler, parviennent à effectuer l'analyse plus approfondie requise par l'absence de typage statique et à produire une compilation juste à temps en code machine (ce qui accélère de plusieurs fois les programmes longs).

1 votes

Quelle est la place de Cython dans ce contexte ? Considérez-vous qu'il s'agit d'un langage différent ou d'une implémentation de Python ? Par ailleurs, cette opposition entre "interprété" et "compilé" n'est-elle pas simplement une confusion terminologique due au fait que la VM de Python est souvent appelée "interprète" ? Il serait tout aussi valable d'appeler la JVM ou le runtime .NET des interprètes. Tous deux interprètent principalement le bytecode en code machine JIT (avec quelques exceptions d'optimisation de la mise en cache).

738voto

unwind Points 181987

Ils contiennent code d'octet qui est le résultat de la compilation du source par l'interpréteur Python. Ce code est ensuite exécuté par la machine virtuelle de Python.

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

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

12 votes

Intéressant, merci. Python est-il donc considéré comme un langage purement interprété ?

216 votes

@froadie : un langage n'est pas "interprété" ou "compilé" en tant que tel. A application spécifique peut être un interprète ou un compilateur (ou un compilateur hybride ou un compilateur JIT).

34 votes

Un test de "compilé" : est-il compilé en instructions machine réelles ? Le bytecode de Python n'est pas une instruction machine, pas plus que les instructions de la JVM de Java, donc aucun de ces langages n'est compilé selon cette définition. Mais tous deux sont "compilés" vers un code "machine abstrait" intermédiaire, et tous deux sont beaucoup plus rapides que d'exécuter le programme en interprétant plus ou moins directement le code source (ce que fait le vieux BASIC).

208voto

Jörg W Mittag Points 153275

Il n'existe pas de langage interprété. L'utilisation d'un interpréteur ou d'un compilateur est purement une caractéristique du langage interprété. mise en œuvre et n'a absolument rien à voir avec la langue.

Chaque peut être implémenté soit par un interprète, soit par un compilateur. La grande majorité des langages ont au moins une implémentation de chaque type. (Par exemple, il existe des interpréteurs pour C et C++ et des compilateurs pour JavaScript, PHP, Perl, Python et Ruby). En outre, la majorité des implémentations des langages modernes combinent en fait à la fois un interprète et un compilateur (voire plusieurs compilateurs).

Un langage n'est qu'un ensemble de règles mathématiques abstraites. Un interpréteur est l'une des nombreuses stratégies concrètes de mise en œuvre d'un langage. Ces deux éléments se situent à des niveaux d'abstraction complètement différents. Si l'anglais était un langage typé, l'expression "langage interprété" serait une erreur de type. L'affirmation "Python est un langage interprété" n'est pas seulement fausse (parce qu'être fausse impliquerait que l'affirmation a un sens, même si elle est fausse), elle n'a tout simplement aucun sens. sens parce qu'une langue peut jamais être défini comme "interprété".

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

  • IronPython : compile en arbres DLR qui sont ensuite compilés en bytecode CIL. Ce qu'il advient du bytecode CIL dépend du CLI VES que vous utilisez, 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 chauds, qu'il compile ensuite en bytecode JVML. Ce qui arrive au bytecode JVML dépend de la JVM sur laquelle vous vous exécutez. Maxine le compilera directement en code natif non optimisé jusqu'à ce qu'il identifie les chemins de code chauds, qu'il recompilera ensuite en code natif optimisé. HotSpot interprétera d'abord le bytecode JVML, puis compilera éventuellement les chemins de code chauds en code machine optimisé.
  • PyPy : compile en bytecode PyPy, qui est ensuite interprété par la VM PyPy jusqu'à ce qu'elle identifie les chemins de code chauds qu'elle compile ensuite en code natif, en bytecode JVML ou en bytecode CIL en fonction de la plateforme sur laquelle vous vous exécutez.
  • CPython : compile en bytecode CPython qu'il interprète ensuite.
  • Stackless Python : compile en bytecode CPython qu'il interprète ensuite.
  • Unladen Swallow : compile en bytecode CPython qu'il interprète ensuite jusqu'à ce qu'il identifie les chemins de code chauds 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 que chacune des implémentations de cette liste (plus quelques autres que je n'ai pas mentionnées, comme tinypy, Shedskin ou Psyco) possède un compilateur. En fait, pour autant que je sache, il n'y a actuellement aucune implémentation de Python qui soit purement interprétée, aucune implémentation de ce type n'est prévue et il n'y en a jamais eu.

Non seulement le terme "langage interprété" n'a pas de sens, mais même si vous l'interprétez comme signifiant "langage avec implémentation interprétée", c'est clairement faux. La personne qui vous a dit cela ne sait manifestement pas de quoi elle parle.

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

7 votes

Les basiques de la vieille école comme le MSBASIC n'avaient pas de forme intermédiaire. Le programme était interprété directement à partir de la forme source (ou quasi source, une forme dans laquelle les mots-clés étaient représentés par des jetons de 1 octet, et les numéros de ligne par des ints binaires de 2 octets, mais le reste était juste de l'ASCII). Donc, en fait, un 'goto' prenait plus ou moins de temps selon le nombre de lignes sources qu'il devait parcourir pour trouver la destination correspondante. Des expressions comme a*b-2*cos(x) étaient effectivement ré-analysées à chaque fois qu'elles étaient exécutées.

6 votes

@greggo : Et si vous voulez faire encore plus old-school, les original version de BASIC était un compilateur de code natif. Cela devrait prouver à quel point la notion de langage "compilé" ou "interprété" est ridicule.

0 votes

Merci d'avoir expliqué comment se comportent les différents compilateurs/interprètes de python. Je me demande s'il existe déjà de bons compilateurs Python qui génèrent un C ou un 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.

66voto

Tim Pietzcker Points 146308

Ceux-ci sont créés par l'interpréteur Python lorsqu'un fichier .py est importé, et ils contiennent le "bytecode compilé" du module/programme importé, l'idée étant que la "traduction" du code source vers le bytecode (qui ne doit être effectuée qu'une seule fois) peut être ignorée lors des importations suivantes. import s si le .pyc est plus récent que le .py ce qui accélère un peu le démarrage. Mais c'est toujours interprété.

10 votes

Vrai. Sauf que de nombreuses bibliothèques de base de Python sont écrites en C. Ainsi, certaines parties de Python sont interprétées, d'autres sont exécutées en C. Vous pouvez faire de même pour vos propres parties de code sensibles aux performances.

20voto

Jerry Coffin Points 237758

Python (du moins son implémentation la plus courante) suit un modèle qui consiste à compiler la source originale en codes d'octets, puis à interpréter ces codes d'octets sur une machine virtuelle. Cela signifie que (encore une fois, l'implémentation la plus courante) n'est ni un interprète pur ni un compilateur pur.

Le revers de la médaille est que le processus de compilation est en grande partie caché - les fichiers .pyc sont traités comme un cache ; ils accélèrent les choses, mais vous n'avez normalement pas besoin d'en être conscient. Il les invalide et les recharge automatiquement (recompile le code source) lorsque cela est nécessaire, en se basant sur l'horodatage des fichiers.

La seule fois où j'ai vu un problème avec cela, c'était quand un fichier bytecode compilé obtenait un timestamp bien dans le futur, ce qui signifiait qu'il semblait toujours plus récent que le fichier source. Puisqu'il semblait plus récent, le fichier source n'était jamais recompilé, donc peu importe les changements que vous faisiez, ils étaient ignorés...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X