web-dev-qa-db-fra.com

Comment feriez-vous l'équivalent des directives de préprocesseur en Python?

Y at-il un moyen de faire les directives de préprocesseur suivantes en Python?

#if DEBUG

< do some code >

#else

< do some other code >

#endif
52
intrepion

Il existe __debug__, qui est une valeur spéciale que le compilateur effectue un prétraitement. 

if __debug__:
  print "If this prints, you're not running python -O."
else:
  print "If this prints, you are running python -O!"

__debug__ sera remplacé par une constante 0 ou 1 par le compilateur et l'optimiseur supprimera toutes les lignes if 0: avant que votre source ne soit interprétée.

97
habnabit

J'ai écrit un préprocesseur python appelé pypreprocessor qui fait exactement ce que vous décrivez.

Le source et la documentation sont disponibles sur Google Code .

Le paquet peut également être téléchargé/installé via PYPI .

Voici un exemple pour accomplir ce que vous décrivez.

from pypreprocessor import pypreprocessor

pypreprocessor.parse()

#define debug

#ifdef debug
print('The source is in debug mode')
#else
print('The source is not in debug mode')
#endif

pypreprocessor est capable de beaucoup plus que du prétraitement à la volée. Pour voir plus d'exemples de cas d'utilisation, consultez le projet sur Google Code.

Update: Plus d'informations sur pypreprocessor

La façon dont je réalise le prétraitement est simple. Dans l'exemple ci-dessus, le préprocesseur importe un objet pypreprocessor créé dans le module pypreprocessor. Lorsque vous appelez parse () sur le préprocesseur, il utilise automatiquement le fichier dans lequel il est importé et génère une copie temporaire de lui-même qui commente tout le code du préprocesseur (afin d'éviter que le préprocesseur ne s'appelle lui-même de manière récursive dans une boucle infinie) et commente toutes les portions non utilisées.

La mise en commentaire des lignes est, par opposition à leur suppression, nécessaire pour conserver les numéros de ligne sur les traces d'erreur si le module lève une exception ou se bloque. Et je suis même allé jusqu'à réécrire le traçage d'erreur pour indiquer le nom de fichier correct du module qui s'est écrasé.

Ensuite, le fichier généré contenant le code post-traité est exécuté à la volée.

L'avantage d'utiliser cette méthode en ajoutant simplement un ensemble d'instructions if si insérées dans le code est qu'il n'y aura pas de temps d'exécution gaspillé à évaluer des instructions inutiles car les portions du code commentées seront exclues des fichiers .pyc compilés.

L’inconvénient (et la raison originale de la création du module) est que vous ne pouvez pas exécuter à la fois python 2x et python 3x dans le même fichier car l’interpréteur pythons exécute une vérification de la syntaxe complète avant l’exécution du code et rejette tout code spécifique à la version avant la fin. préprocesseur est autorisé à exécuter :: sigh ::. Mon objectif initial était de pouvoir développer côte à côte un code 2x et 3x dans le même fichier, ce qui créerait un code secondaire spécifique à la version, en fonction de son exécution.

Quoi qu'il en soit, le module de préprocesseur reste très utile pour la mise en œuvre des capacités de pré-traitement communes de type c. En outre, le préprocesseur est capable de générer le code post-traité dans un fichier pour une utilisation ultérieure, si vous le souhaitez.

En outre, si vous souhaitez générer une version contenant toutes les directives du préprocesseur ainsi que les #ifdefs exclus, supprimez-la, il suffit de définir un indicateur dans le code du préprocesseur avant d'appeler parse (). Cela fait de la suppression de code non désiré d'un fichier source spécifique à la version un processus en une étape (vs analyse du code et suppression manuelle des instructions if). 

31
Evan Plaice

Je suppose que tu vas détester cette réponse. La façon dont vous faites cela en Python est

# code here
if DEBUG:
   #debugging code goes here
else:
   # other code here.

Puisque python est un interpréteur, il n’ya pas d’étape de prétraitement à appliquer ni d’avantage particulier d’avoir une syntaxe spéciale. 

22
Charlie Martin

Vous pouvez utiliser le préprocesseur en Python. Il suffit de lancer vos scripts via le cpp (C-Preprocessor) dans votre répertoire bin. Cependant, je l'ai fait avec Lua et les avantages d'une interprétation facile ont dépassé la compilation plus complexe IMHO.

10
Robert Gould

Vous pouvez simplement utiliser les constructions de langage normales:

DEBUG = True
if DEBUG:
  # Define a function, a class or do some crazy stuff
  def f():
    return 23
else:
  def f():
    return 42
3
phihag

Une autre méthode consiste à utiliser un script bash pour commenter des parties de code qui ne concernent que le débogage. Vous trouverez ci-dessous un exemple de script qui commente les lignes contenant une instruction '#DEBUG'. Il peut également supprimer ces marqueurs de commentaires.

if [ "$1" == "off" ]; then
  sed -e '/^#/! {/#DEBUG/ s/^/#/}' -i *.py
  echo "Debug mode to $1"
Elif [ "$1" == "on" ]; then
  sed -e '/#DEBUG/ s/^#//' -i *.py
  echo "Debug mode to $1"
else
  echo "usage: $0 on | off"
fi
1
slierp
  • Python si ne peut pas éliminer les éléments des tableaux.
  • Les précompilateurs C ne gèrent pas #! ou d'autres lignes commençant par # si nécessaire.
  • pypreprocessor semble être spécifique à Python

Utilisez plutôt un m4 commun, comme ceci:

ifelse(DEBUG,True,dnl`
  < do some code >
dnl,dnl`
  < do some other code >dnl
')

ifelse(
  M4_CPU,x86_64,`
    < do some code specific for M4_CPU >
',M4_CPU,arm,`
    < do some code specific for M4_CPU >
',M4_CPU,ppc64le,`
    < do some code specific for M4_CPU >
')

ifelse(
  M4_OS,windows,`
    < do some code specific for M4_OS >
  ',M4_OS,linux,`
    < do some code specific for M4_OS >
  ',M4_OS,Android,`
    < do some code specific for M4_OS >
')

m4 -D DEBUG = True -D M4_OS = Android -D M4_CPU = armer test.py.m4> test.py

0
Torsten Reichert