python: argument et fichier de configuration

Gestion des arguments par argparse

exemple de mise en place de prise en charge des arguments en python

import argparse

parser = argparse.ArgumentParser(description='xxxx', epilog='xxxx')
parser.add_argument('-a', action='store_true', default=False, help='Activation du drapeau a')
parser.add_argument('-v', '--version', dest='VERSION', action='store_true', default=False, help='Affichage de la version de la commande')
parser.add_argument('-l', action='append', help='liste de valeur')
parser.add_argument('-i', action='store', type=int, default=10, help='valeur int')
parser.add_argument('-j', action='store', type=int, required=True, metavar='jjjj', help='valeur int2')
#argument obligatoire, jjj apparaitra daans l'utilisation help

parser.add_mutually_exclusive_group('login') #argument r et l sont exclusives
parser.add_argument('-r', action='store', type=int, metavar='left', help='valeur left')
parser.add_argument('-l', action='store', type=int, metavar='right', help='valeur right')

args = parser.parse_args()
print args
print args.a
print args.VERSION
print args.l #permet d'utiliser myprog -l=1 -l=2 ...

Gestion des arguments par OptionParser

exemple de mise en place de prise en charge des arguments en python

from optparse import OptionParser
import sys
import os, os.path

def get_path_file(p):
    """
    Test of p is file with pwd, user path, PYTHONPATH  and PATH
    """
    if os.path.isfile(p):
        return p
    if os.path.isfile(os.path.join(os.getcwd(),p)):
        return os.path.join(os.getcwd(),p)
    if os.path.isfile(os.path.join(os.path.expanduser('~'),p)):
        return os.path.join(os.path.expanduser('~'),p)
    for i in sys.path:
        if os.path.isfile(os.path.join(i,p)):
            return os.path.join(i,p)
        if os.path.isfile(os.path.join(os.path.dirname(i),p)):
            return os.path.join(os.path.dirname(i),p)
    for i in  os.environ['PATH']:
        if os.path.isfile(os.path.join(i,p)):
            return os.path.join(i,p)
    raise AttributeError, '%s is not file' % p

def get_path_dir(p):
    """
    Test of p is dir with pwd, user path, PYTHONPATH  and PATH
    """
    if os.path.isdir(p):
        return p
    if os.path.isdir(os.path.join(os.getcwd(),p)):
        return os.path.join(os.getcwd(),p)
    if os.path.isdir(os.path.join(os.path.expanduser('~'),p)):
        return os.path.join(os.path.expanduser('~'),p)
    for i in sys.path:
        if os.path.isdir(os.path.join(i,p)):
            return os.path.join(i,p)
        if os.path.isdir(os.path.join(os.path.dirname(i),p)):
            return os.path.join(os.path.dirname(i),p)
    for i in  os.environ['PATH']:
        if os.path.isdir(os.path.join(i,p)):
            return os.path.join(i,p)
    raise AttributeError, '%s is not file' % p

def printer(a,b,c):
    print a,b,c

if __name__ == '__main__':
    parser = OptionParser(version="%prog 0.1" usage= "usage: %prog [options] args" )
    parser.description= "description"
    parser.epilog = "by Frederic Aoustin"
    parser.add_option("-d", "--dir",
        dest="rep",
        help ="le dossier contenant mes photos(mettre / en fin de nom)",
        type="int")
    parser.add_option("-f", "--fic",
        dest="fic",
        help ="is required",
        type="string")
    parser.add_option("-b",  "--bol",
        action="store_true",
        dest="bol",
        default=False,
        help ="test boolean")
    parser.add_option("-a", "--action",
        dest="act",
        choices = ['deploy', 'start', 'stop'],
        help ="action",
        default="start",
        type="choice")
    (options, args) = parser.parse_args()
    try:
        print args
        rep = get_path_dir(options.rep)
        fic = get_path_file(options.fic)
        bol = options.bol
        print(options.a)
        printer(rep , fic, bol)
    except Exception, e:
        print parser.error(e)
        parser.print_help()
        sys.exit(1)

Note

avec python3 il faut noter que

raise AttributeError, '%s is not directory' % p

devient

raise AttributeError('%s is not directory' % p)

et que

print a,b,c

devient

print(a,b,c)

Note

on peut gére la liste des choix, le type, ... il faut beaucoup travailler avec ce module cela évite bien des contrôles par la suite

on peut aussi utiliser le code suivant pour définir le path d’un fichier

import sys
from os import path

package_dir = path.abspath(path.dirname(__file__))
print(package_dir)

utilisation

python test.py -d 1 --fic titi --bol arg1 arg2
>>['arg1','arg2']
>> 1 titi True
python test.py -d 1 -f titi
>> []
>> 1 titi False
python test.py -d a
>> Usage: test.py [options] args
>> test.py: error: option -d: invalid integer value: 'a'
python test.py --help
>>Usage: test.py [options] args
>> Description
>>Options:
>> -h, --help         show this help message and exit
>> -d REP, --dir=REP  le dossier contenant mes photos(mettre / en fin de nom)
>> -f FIC, --fic=FIC  is required
>> -b, --bol          test boolean
>> -a, --action=ACT   action
>> by Frédéric Aoustin

Note

si vous ajouter des règles de présence par exemple il est possible de lever une exception en utilisant parser.error(“invalid number of arguments”)

On peut aussi souhaiter avoir une constante qui a pour valeur False et devient True si on la nomme. Cela s’exprime ainsi

parser.add_option("-v", action="store_true", dest="opt1", default=False)
parser.add_option("-q", action="store_false", dest="opt2", default=True)
  • opt1 à pour valeur par défaut False
  • opt2 à pour valeur par défaut True

la ligne suivante

python test.py -v

fera que :

  • opt1 à pour valeur par défaut True
  • opt2 à pour valeur par défaut True

On peut enfin avoir des sorties colorées en utilisant le module colorconsole (et faire que les erreurs traitées pas optparse soient colorisées

import colorconsole, colorconsole.terminal
import sys
import keepass
from optparse import OptionParser

VERSION="0.1"
PROG="password"
DESCRIPTION="""command line for KeePass2"""
AUTHOR="Frederic Aoustin"

class OptionParserColor(OptionParser):

    def __init__(self, screen=None, **kw):
        OptionParser.__init__(self, **kw)
        if screen == None:
            screen = colorconsole.terminal.get_terminal()
        self.screen = screen

    def exit(self, status=0, msg=None):
        if msg:
            sys.stderr.write(msg)
        self.screen.set_color(colorconsole.terminal.colors["WHITE"], colorconsole.terminal.colors["BLACK"])
        sys.exit(status)

    def error(self, msg):
        self.screen.set_color(colorconsole.terminal.colors["RED"], None)
        OptionParser.error(self, msg)

    def print_version(self, file=None):
        self.screen.set_color(colorconsole.terminal.colors["GREEN"],None)
        OptionParser.print_version(self, file)
        self.screen.set_color(colorconsole.terminal.colors["WHITE"], colorconsole.terminal.colors["BLACK"])

    def print_help(self, file=None):
        self.screen.set_color(colorconsole.terminal.colors["GREEN"],None)
        OptionParser.print_help(self, file)
        self.screen.set_color(colorconsole.terminal.colors["WHITE"], colorconsole.terminal.colors["BLACK"])

    def print_info(self, msg=""):
        self.screen.set_color(colorconsole.terminal.colors["LGREEN"],None)
        print(msg)
        self.screen.set_color(colorconsole.terminal.colors["WHITE"], colorconsole.terminal.colors["BLACK"])

    def print_stdout(self, msg, fg="WHITE", bg="BLACK"):
        self.screen.set_color(colorconsole.terminal.colors[fg],colorconsole.terminal.colors[bg])
        sys.stdout.write(msg)
        self.screen.set_color(colorconsole.terminal.colors["WHITE"], colorconsole.terminal.colors["BLACK"])



if __name__ == '__main__':
    parser = OptionParserColor(version="%s %s" % (PROG,VERSION))
    parser.description= DESCRIPTION
    parser.epilog = AUTHOR
    parser.add_option("-f", "--file-keepass",
        dest="fkeepass",
        help ="database KeePass2",
        default=None ,
        type="string")
    parser.add_option("-k", "--key",
        dest="key",
        help ="key for open database KeePass2",
        default=None ,
        type="string")
    try:
        (options, args) = parser.parse_args()
        parser.print_info('coucou')
        parser.print_stdout('coucou')
        parser.print_stdout('coucou','LBLUE','LGREEN')
    except Exception as e:
        parser.error(parser, e)
        sys.exit(1)

Utilisation de fichier conf

exemple de fichier conf

[Server]
Base=.
Port=8080
Timeout=3
Appli=test
Cgi=/cgi-bin

utilisation de ce fichier

import ConfigParser
config = ConfigParser.ConfigParser()
config.read('base.conf')
print config.sections()
print config.options('Server')
# exist has_option and has_section
print config.items("Server') #return tuple id, value
CONF_BASE = config.get('Server', 'Base')
CONF_CGI = config.get('Server', 'Cgi')
if CONF_CGI == 'None': CONF_CGI = None
CONF_PORT = config.getint('Server', 'Port')
CONF_TIMEOUT = config.getint('Server', 'Timeout')
# exist getfloat, getboolean

un exemple de lecture de fichier avec auto-identification du type:

import ConfigParser

def returntype(p,s,v):
    try:
        old = p.get(s,v)
        try:
            old = p.getfloat(s,v)
            try:
                old = p.getint(s,v)
            except:
                return old
        except:
            try:
                old = p.getboolean(s,v)
                return old
            except:
                return old
    except:
        raise TypeError("does not exist")



a = ConfigParser.ConfigParser()
a.read('test.cfg')

for name in a.options('Log'):
    print returntype(a,'Log',name), returntype(a,'Log',name).__class__