Logo Blog perso d'Ozwald

Petites astuces vite fait

Par Oz le - Geek
code source python

Pour renouer avec les quelques billets express que j'ai déjà pu faire voici, en vrac, une poignée d'astuces (principalement python) qui pourraient être utiles.

Swiss Knife - Creative Common by "focusforaword" on Flickr

Python2 ou Python3 ? Les deux !

J'ai l'impression que tout le monde code en python2, malheureusement "Python 3.x is the present and future of the language" donc il va bien falloir y passer. Pour ma part j'étais réticent à passer à Python3 principalement à cause d'une unique différence print "toto" en python2 (que je trouvais très pratique) devient print("toto") en python3, or des "print" j'en colle à toutes les sauces dans mes scripts. L'habitude étant ce qu'elle est je me retrouvait toujours à coller un print "toto" quelque part dans mon code et je me disait "oh et puis zut" et je basculais en 100% python2. Aujourd'hui je partage avec vous une "astuce" que j'utilise à présent pour rendre mes scripts compatibles python2 ET python3 : je remplace les print par les fonctions du module standard logging.

import logging
logging.basicConfig(level = logging.DEBUG, format="%(message)s")

//équivalent de 
// print "toto" # en python2
// print("toto") # en python3
logging.debug("toto")

Autre avantage du module logging : ça gère directement les différents niveau de verbosité1. Entre logging.debug, logging.info, logging.warning, et leurs consoeurs vous trouverez forcément le niveau de log qui vous plait; ainsi il n'est plus besoin de commenter en masse les print entre votre version de "dev" et de "prod" ^^

Le C c'est bien, mais parfois il faut l'oublier

J'aime beaucoup le C, mais sur ce coup là ça m'a joué un mauvais tour : quand j'ai voulu parser les arguments de la ligne de commande de mes scripts python je me suis intéressé au module getopt qui ressemble furieusement à ce qui existe en C. Erreur grossière : j'aurai mieux fait de regarder argparse qui est beaucoup plus pythonique et infiniment plus pratique ! A titre de comparaison voilà un exemple typique avec les deux modules. Les arguments possibles sont -h/- -help pour afficher l'aide, ou -v/- -verbose suivi d'un niveau de 0 à 4 pour régler la verbosité du programme. Voilà deux équivalents fonctionnels, l'un avec argparse, l'autre avec getopt :

import argparse, logging

parser = argparse.ArgumentParser(description='Super script de la mort qui tue')
parser.add_argument('--verbose', '-v', type=int, dest='verb', help='verbosity level [0-4]', default=4, choices=[0,1,2,3,4])
args = parser.parse_args()

logging.basicConfig(level = logging.CRITICAL-args.verb*10, format="%(message)s")
logging.debug("Debug") # cette ligne et les 2 suivante servent juste a voir que le setting du niveau de verbose fonctionne
logging.info("Info")
logging.warning("Warning")

Contre :

def usage():
    print "La on a un souci puisqu'on doit utiliser 'print'..."
    print "Et puis surtout on doit ecrire son 'usage' soit-meme alors qu'argparse l'ecrit automatiquement"
    print "Usage : %s [--verbose/-v LEVEL]"%sys.argv[0]
    print " --verbose/-v LEVEL\\tVerbosity level between 0-5 [default to 4]" 

import sys, getopt, logging
try:
    opts, args = getopt.getopt(sys.argv[1:], "v:h", ["verbose", "help"])
except getopt.GetoptError, err:
        print str(err) # will print something like "option -a not recognized"
        usage()
        sys.exit(2)

verbose = 4
for o, a in opts:
    if o in ["-v","--verbose"]:
        try:
            verbose = int(a)
        except:
            usage()
            sys.exit(2)
        if not verbose in [0,1,2,3,4]:
            usage()
            sys.exit(2)
    elif o in ['-h', '--help']:
        usage()
        sys.exit(0)

logging.basicConfig(level = logging.CRITICAL-verbose*10, format="%(message)s")
logging.debug("Debug") # cette ligne et les 2 suivante servent juste a voir que le setting du niveau de verbose fonctionne
logging.info("Info")
logging.warning("Warning")

L'avantage d'argparse est évident pour tout le monde j'espère ! Par contre, bien qu'argparse soit censé être un module standard depuis python2.7, et qu'il soit par défaut présent sur ma ubuntu 12.04, j'ai été obligé de l'installer explicitement sur ma gentoo emerge dev-python/argparse...dommage.

  1. Même si ce mot n'existe pas