Comment éviter les fichiers .pyc?

268

Puis-je exécuter l'interpréteur python sans générer les fichiers .pyc compilés?

Avner
la source

Réponses:

288

De "Quoi de neuf dans Python 2.6 - Modifications de l'interpréteur" :

Python peut désormais être empêché d'écrire des fichiers .pyc ou .pyo en fournissant le commutateur -B à l'interpréteur Python ou en définissant la variable d'environnement PYTHONDONTWRITEBYTECODE avant d'exécuter l'interpréteur. Ce paramètre est disponible pour les programmes Python en tant que sys.dont_write_bytecodevariable, et le code Python peut changer la valeur pour modifier le comportement de l'interpréteur.

Mise à jour 2010-11-27: Python 3.2 résout le problème d'encombrement des dossiers source avec des .pycfichiers en introduisant un __pycache__sous-dossier spécial , voir Nouveautés de Python 3.2 - Répertoires de référentiel PYC .

Constantin
la source
1
Au moins sur OS X 10.8 exécutant Python 2.7, la variable d'environnement n'a aucun effet.
sorin
5
Si vous incorporez l'interpréteur (dans un programme C ++), utilisez "Py_DontWriteBytecodeFlag = 1;" dans votre code source. C'est un entier global déclaré dans pydebug.h.
JimB
1
La variable d'environnement fonctionne très bien pour moi en 2.7, je ne sais pas quels problèmes les autres ont. Merci!
Thomas
8
A aussi fonctionné pour moi sur OSX (10.8 & 10.10); @sorin avez-vous exporté la variable correctement? export PYTHONDONTWRITEBYTECODE=1
nevelis
1
Savez-vous comment faire de même avec pytest?
110
import sys

sys.dont_write_bytecode = True
te wilson
la source
25
Je viens de l'essayer et cela fonctionne pour les modules importés. Plus précisément, une fois cette variable définie, tout élément importé plus tard ne générera pas de fichiers pyc. C'est délicieux. Merci.
Plutôt l'ajouter dans le module parent, essayez de l'ajouter dans le script référencé. Cela fonctionne bien. Merci à @te wilson
Sathy
4
Ajoutez ceci à votre site-packages/usercustomize.pypour que cela s'applique à tous vos scripts. Pour moi, ce répertoire était $HOME/.local/lib/python2.6/site-pacakges/usercustomize.py. Cf. docs.python.org/2/tutorial/…
RobM
3
Mon site-packages était situé à: /usr/local/lib/python2.7/site-packages et j'ai dû créer usercustomize.py
anon58192932
3
Ou en une seule ligne:import sys; sys.dont_write_bytecode = True
ET-CS
23

Il existe en fait un moyen de le faire dans Python 2.3+, mais c'est un peu ésotérique. Je ne sais pas si vous vous en rendez compte, mais vous pouvez faire ce qui suit:

$ unzip -l /tmp/example.zip
 Archive:  /tmp/example.zip
   Length     Date   Time    Name
 --------    ----   ----    ----
     8467  11-26-02 22:30   jwzthreading.py
 --------                   -------
     8467                   1 file
$ ./python
Python 2.3 (#1, Aug 1 2003, 19:54:32) 
>>> import sys
>>> sys.path.insert(0, '/tmp/example.zip')  # Add .zip file to front of path
>>> import jwzthreading
>>> jwzthreading.__file__
'/tmp/example.zip/jwzthreading.py'

Selon la bibliothèque zipimport :

Tous les fichiers peuvent être présents dans l'archive ZIP, mais seuls les fichiers .py et .py [co] sont disponibles pour l'importation. L'importation ZIP de modules dynamiques (.pyd, .so) n'est pas autorisée. Notez que si une archive contient uniquement des fichiers .py, Python ne tentera pas de modifier l'archive en ajoutant le fichier .pyc ou .pyo correspondant, ce qui signifie que si une archive ZIP ne contient pas de fichiers .pyc, l'importation peut être assez lente.

Ainsi, tout ce que vous avez à faire est de compresser les fichiers, d'ajouter le fichier zip à votre sys.path puis de les importer.

Si vous construisez cela pour UNIX, vous pouvez également envisager de compresser votre script à l'aide de cette recette: exécutable zip unix , mais notez que vous devrez peut-être le modifier si vous prévoyez d'utiliser stdin ou de lire quoi que ce soit à partir de sys.args (cela PEUT être sans trop de peine).

D'après mon expérience, les performances ne souffrent pas trop à cause de cela, mais vous devriez réfléchir à deux fois avant d'importer de très gros modules de cette façon.

Jason Baker
la source
11

En 2.5, il n'y a aucun moyen de le supprimer, à part des mesures comme ne pas donner aux utilisateurs un accès en écriture au répertoire.

En python 2.6 et 3.0 cependant, il peut y avoir un paramètre dans le module sys appelé "dont_write_bytecode" qui peut être défini pour supprimer cela. Cela peut également être défini en passant l'option "-B" ou en définissant la variable d'environnement "PYTHONDONTWRITEBYTECODE"

Brian
la source
7

Vous pouvez définir sys.dont_write_bytecode = Truevotre source, mais cela devrait être dans le premier fichier python chargé. Si vous exécutez, python somefile.pyvous n'obtiendrez passomefile.pyc .

Lorsque vous installez un utilitaire à l'aide setup.pyet entry_points=vous aurez défini sys.dont_write_bytecodedans le script de démarrage. Vous ne pouvez donc pas vous fier au script de démarrage "par défaut" généré par setuptools.

Si vous démarrez vous-même Python avec un fichier python comme argument, vous pouvez spécifier -B:

python -B somefile.py

somefile.pycne serait pas généré de toute façon, mais aucun .pycfichier pour les autres fichiers importés aussi.

Si vous avez un utilitaire myutilet que vous ne pouvez pas le changer, il ne passera pas -B à l'interpréteur python. Il suffit de le démarrer en définissant la variable d'environnement PYTHONDONTWRITEBYTECODE:

PYTHONDONTWRITEBYTECODE=x myutil
Elwyne
la source
4

J'ai plusieurs cas de test dans une suite de tests et avant d'exécuter la suite de tests dans le terminal Mac comme ceci:

python LoginSuite.py

En exécutant la commande de cette façon, mon répertoire était rempli de fichiers .pyc. J'ai essayé la méthode indiquée ci-dessous et cela a résolu le problème:

python -B LoginSuite.py

Cette méthode fonctionne si vous importez des cas de test dans la suite de tests et exécutez la suite sur la ligne de commande.

Ravil Asadov
la source
4

À partir de Python 3.8, vous pouvez utiliser la variable d'environnement PYTHONPYCACHEPREFIXpour définir un répertoire de cache pour Python.

Depuis les documents Python:

Si ce paramètre est défini, Python écrira les fichiers .pyc dans une arborescence de répertoires miroir sur ce chemin, plutôt que dans les répertoires pycache de l'arborescence source. Cela revient à spécifier l'option -X pycache_prefix = PATH.

Exemple

Si vous ajoutez la ligne suivante à votre ./profilesous Linux:

export PYTHONPYCACHEPREFIX="$HOME/.cache/cpython/"

Python ne créera pas les __pycache__répertoires ennuyeux dans le répertoire de votre projet, mais les placera tous sous~/.cache/cpython/

Rotareti
la source
2

Vous pouvez rendre les répertoires dans lesquels vos modules existent en lecture seule pour l'utilisateur sous lequel l'interpréteur Python s'exécute.

Je ne pense pas qu'il existe une option plus élégante. PEP 304 semble avoir été une tentative d'introduire une option simple pour cela, mais il semble avoir été abandonné.

J'imagine qu'il y a probablement un autre problème que vous essayez de résoudre, pour lequel la désactivation de .py [co] semblerait être une solution de contournement, mais il serait probablement préférable d'attaquer à la place ce problème d'origine.

Logan
la source
2

Solution pour ipython 6.2.1 using python 3.5.2(Testé sur Ubuntu 16.04 et Windows 10):

Ipythonne respecte pas %env PYTHONDONTWRITEBYTECODE =1s'il est défini dans l' ipythoninterpréteur ou lors du démarrage dans ~/.ipython/profile-default/startup/00-startup.ipy. Utilisez plutôt les éléments suivants dans votre~.ipython/profile-default/startup/00-startup.py

import sys
sys.dont_write_bytecode=True
alpha_989
la source
0

Autant que je sache, python compilera tous les modules que vous "importerez". Cependant, python ne compilera PAS un script python exécuté en utilisant: "python script.py" (il compilera cependant tous les modules que le script importe).

La vraie question est pourquoi vous ne voulez pas que python compile les modules? Vous pourriez probablement automatiser un moyen de les nettoyer s'ils gênent.

Alex
la source
J'ai constaté fréquemment qu'il existe des .pycfichiers de bytecode périmés . Pour une raison quelconque, lorsque je change de classe / module, le .pycfichier n'est pas mis à jour. Ainsi, lorsque je l'importerai après avoir modifié le .pyfichier, il utilisera toujours le .pycfichier, ce qui entraînera des erreurs
alpha_989