web-dev-qa-db-fra.com

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

On m'a donné à comprendre que Python est un langage interprété ... Cependant, lorsque je regarde mon code source Python, je vois des fichiers .pyc que Windows identifie comme "Compilé Python Fichiers". Où viennent-ils?

974
froadie

Ils contiennent code d'octet , ce à quoi l’interprète 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 suit:

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 code-octet. Cela signifie que les fichiers source peuvent être exécutés directement sans créer explicitement un exécutable qui sera ensuite exécuté.

610
unwind

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

Ce mème populaire est incorrect ou plutôt construit sur une incompréhension des niveaux de langage (naturel): une erreur similaire consisterait à dire "la Bible est un livre à couverture rigide". Laissez-moi expliquer cette comparaison ...

"La Bible" est "un livre" dans le sens d'être une classe de (objets physiques réels identifiés comme) des livres; les livres identifiés comme "copies de la Bible" sont supposés avoir quelque chose de fondamental en commun (le contenu, même ceux pouvant être en différentes langues, avec différentes traductions acceptables, niveaux de notes de bas de page et autres annotations) - cependant, ces livres sont: parfaitement autorisé à différer dans une multitude d'aspects qui sont et non considérés comme fondamentaux - type de reliure, couleur de la reliure, police (s) utilisée (s) dans le logiciel l’impression, les illustrations éventuelles, les marges larges en écriture ou non, le nombre et le type de signets intégrés, etc., etc.

Il est tout à fait possible qu'une impression de la Bible typique soit effectivement reliée à la reliure rigide. Après tout, c'est un livre qui est généralement destiné à être lu et lu. dessus, marque-pages à plusieurs endroits, feuilleté à la recherche d'indicateurs de chapitres et de versets donnés, etc., etc., et une bonne reliure cartonnée peut faire durer une copie donnée plus longtemps avec 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 donné est une copie de la Bible ou non: les impressions de poche sont parfaitement possibles!

De même, Python est "un langage" dans le sens de définir une classe de langage implémentations qui doivent tous être similaires à certains égards fondamentaux (syntaxe, la plupart des sémantiques, à l'exception des parties de celles où ils sont explicitement autorisés à différer) mais tout à fait autorisés à différer dans à peu près tous les détails de "mise en oeuvre" - y compris la manière dont ils traitent avec la source les fichiers qu’ils reçoivent, qu’ils compilent les sources dans des formulaires de niveau inférieur (et, le cas échéant, quel formulaire - et qu’ils sauvegardent ces formulaires compilés, sur disque ou ailleurs), comment ils exécutent ces formulaires, etc.

L'implémentation classique, CPython, est souvent appelée simplement "Python" - mais ce n'est qu'une implémentation de qualité production, aux côtés d'IronPython de Microsoft (qui compile en codes CLR, c'est-à-dire ".NET"), Jython (qui compile en codes JVM), PyPy (qui est écrit en Python lui-même et peut compiler une grande variété de formes "d’arrière-plan", y compris le langage machine généré juste-à-temps). Ils sont tous Python (== "implémentations du langage Python _"), tout comme de nombreux objets de livre superficiellement différents peuvent tous être des Bibles (== "copies de The Bible").

Si vous êtes intéressé par CPython en particulier: il compile les fichiers source dans un formulaire de niveau inférieur spécifique à Python (appelé "bytecode"), le fait automatiquement en cas de besoin (quand aucun fichier bytecode ne correspond à un fichier source, ou le fichier de bytecode est plus ancien que la source ou compilé par une autre version 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 les codes CLR (en les enregistrant sur disque ou non, selon le cas) et les codes Jython en JVM (en les enregistrant sur disque ou non - il utilisera l'extension .class s'il les enregistre).

Ces formulaires de niveau inférieur sont ensuite exécutés par les "machines virtuelles" appropriées, également appelées "interprètes" - la machine virtuelle CPython, le moteur d'exécution .Net, le Java VM (aussi appelée 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 sont: ils ont tous une stratégie d'implémentation typique de produisant d’abord le bytecode, puis l’exécutant via un interpréteur/VM.

Plus probablement, l'accent est mis sur le processus de compilation "lourd", lent et fastueux. CPython est conçu pour compiler le plus rapidement possible, le plus léger possible, avec le moins de cérémonie possible - le compilateur effectue très peu de vérification des erreurs et d’optimisation, afin de pouvoir fonctionner rapidement et avec une petite quantité de mémoire, ce qui permet à son tour être exécuté automatiquement et de manière transparente chaque fois que 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 lors de la compilation (et n'effectuent donc pas de compilation automatique) afin de vérifier les erreurs de manière plus approfondie et d'effectuer davantage d'optimisations. C'est un continuum d'échelles de gris, pas une situation de noir ou de blanc, et il serait totalement arbitraire de placer un seuil à un niveau donné et de dire que ce n'est qu'au-dessus de ce niveau que vous appelez cela "compilation"! -)

926
Alex Martelli

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

Chaque langage peut être implémenté 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éteurs pour C et C++ et des compilateurs pour JavaScript, PHP, Perl, Python et Ruby.) De plus, la plupart des implémentations en langage moderne combinent à la fois un interpréteur et un compilateur ( ou même plusieurs compilateurs).

Une langue n'est qu'un ensemble de règles mathématiques abstraites. Un interprète est l’une des stratégies de mise en œuvre concrètes d’une langue. Ces deux 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. L’affirmation "Python est un langage interprété" n’est pas simplement fausse (car être faux impliquerait que l’affirmation ait même un sens, même si elle est fausse), elle ne signifie tout simplement pas que sens, car une langue peut jamais être définie comme "interprétée".

En particulier, si vous regardez les implémentations Python actuellement existantes, vous trouverez ci-dessous les stratégies d'implémentation qu'elles utilisent:

  • IronPython: compile dans des arbres DLR que le DLR compile ensuite en bytecode CIL. Ce qui arrive au bytecode CIL dépend du VES CLI sur lequel vous exécutez, mais Microsoft .NET, GNU Portable.NET et Novell Mono le compileront éventuellement en code machine natif.
  • Jython: interprète Python code source jusqu'à ce qu'il identifie les chemins d'accès au code dynamique, qu'il compile ensuite en bytecode JVML. Ce qui arrive au bytecode JVML dépend de la machine virtuelle sur laquelle vous exécutez la machine virtuelle. Maxine le compilera directement dans du code natif non optimisé jusqu'à ce qu'il identifie les chemins de code chaud, qu'il recompilera ensuite en code natif optimisé. HotSpot interprétera d’abord le bytecode JVML, puis compilera les chemins de code chauds en code machine optimisé.
  • PyPy: compile en bytecode PyPy, qui est ensuite interprété par PyPy VM jusqu'à ce qu'il identifie les chemins de code chaud qu'il compile ensuite en code natif, en bytecode JVML ou en Ctt, en fonction de la plate-forme sur laquelle vous exécutez l'exécution.
  • 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 pour LLVM IR et 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 un 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) possède un compilateur. En fait, à ma connaissance, il n’existe actuellement aucune Python implémentation interprétée purement, aucune implémentation de ce type n’est prévue et aucune implémentation de ce type n’a jamais eu lieu.

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

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

150
Jörg W Mittag

Ceux-ci sont créés par l’interprète Python lorsqu’un fichier .py est importé et contiennent le "bytecode compilé" du module/programme importé, l’idée étant que la "traduction" du code source Le bytecode (qui ne doit être fait qu'une seule fois) peut être ignoré à la suite de imports si le .pyc est plus récent que le fichier .py correspondant, accélérant ainsi un peu le démarrage. Mais c'est toujours interprété.

59
Tim Pietzcker

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

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

Dans python3, la machine d'importation de Python est étendue pour écrire et rechercher des fichiers cache de code d'octet dans un répertoire unique dans chaque répertoire de package Python. Ce répertoire s'appellera __pycache__.

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

enter image description here

Pour plus d'informations:

ref: PEP3147
ref: fichiers "Compilés" Python

36
hxysayhi

This IS for debutants,

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

L'exécution d'un script n'est pas considérée comme une importation et aucun fichier .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éé car xyz est importé, mais aucun fichier abc.pyc ne sera créé car abc.py n'est pas importé.

Si vous devez créer un fichier .pyc pour un module non importé, vous pouvez utiliser les modules py_compile et compileall.

Le module py_compile peut compiler manuellement n’importe quel module. Une solution consiste à utiliser la fonction py_compile.compile 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 par 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 actuel dans cet exemple) est omis, le module compile tout ce qui se trouve sur sys.path.

35
MAX

Python (du moins son implémentation la plus courante) suit un modèle de compilation de la source d’origine en codes octets, puis en interprétant les codes octets sur une machine virtuelle. Cela signifie (encore une fois, l'implémentation la plus courante) n'est ni un interpréteur pur, ni un compilateur pur.

Toutefois, le processus de compilation est en grande partie masqué. Les fichiers .pyc sont fondamentalement traités comme un cache. ils accélèrent les choses, mais vous n'avez normalement pas à en être conscients. Il les invalide automatiquement et les recharge (recompile le code source) lorsque cela est nécessaire en fonction des horodatages des fichiers.

À peu près la seule fois où j'ai vu un problème avec cela, c'est quand un fichier bytecode compilé a reçu un horodatage bien à l'avenir, ce qui signifie qu'il avait 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 quels que soient les changements apportés, ils ont été ignorés ...

20
Jerry Coffin

Le fichier * .py de Python est simplement un fichier texte dans lequel vous écrivez des lignes de code. Lorsque vous essayez d'exécuter ce fichier en utilisant "python nomfichier.py"

Cette commande appelle Python Machine virtuelle. Python La machine virtuelle a 2 composants: "compilateur" et "interprète". L'interprète ne peut pas lire directement le texte dans le fichier * .py. Ce texte est donc d'abord converti en un octet qui est destiné au PVM (pas au matériel, mais au 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 un fichier dans Shell ou dans un autre fichier.

Si ce fichier * .pyc est déjà généré, à chaque fois que vous exécuterez/exécuterez votre fichier * .py, le système chargera directement votre fichier * .pyc, qui ne nécessitera aucune compilation (cela vous fera économiser quelques cycles de processeur).

Une fois que le fichier * .pyc est généré, vous n'avez plus besoin du fichier * .py, sauf si vous le modifiez.

12
Vishal Mopari

Le code Python passe par 2 étapes. La première étape consiste à compiler le code en fichiers .pyc, qui est en fait un bytecode. Ensuite, ce fichier .pyc (bytecode) est interprété à l'aide d'un interpréteur CPython. S'il vous plaît se référer à this link. Ici, le processus de compilation et d'exécution du code est expliqué facilement.

7
Tango