[Python] variabili "globali" tra più moduli.
Daniele Varrazzo
piro a develer.com
Lun 20 Maggio 2013 01:48:57 CEST
On 2013-05-18 09:26, Marco Beri wrote:
> Il giorno 18/mag/2013 01:33, "Daniele Varrazzo" <piro a develer.com> ha
> scritto:
>> Guarda optparse o argparse nella libreria python. Entrambi
>> restituiscono
> un oggetto che contiene tutti i parametri come attributi. Tipicamente
> ottieni quello nel main() e poi passi l'oggetto o solo i valori che
> servono
> a funzioni o oggetti create nel main.
>
> Ad un talk a djangocon, non nella libreria standard, hanno segnalato
> questa
> bella libreria standard:
>
> https://github.com/docopt/docopt
"questa bella libreria", non standard.
La conosco. Gneh. Mah. Non mi ha fatto godere. La usa un mio collega:
il giochino è che tutte le volte prova a ficcarla nei progetti dove
lavoro anche io gliela rimuovo e la sostituisco con optparse o argparse.
Non amo forzare un messaggio pensato per il consumo umano ad assumere
tutti i vincoli necessari perché un computer lo capisca. È la stessa
critica che muovo a doctest. Bello come giochino ma a farci qualcosa di
serio e mantenerlo la vedo pesa.
In particolare di solito devo mettere due opzioni in croce e per quello
uso optparse. Un mio progetto (PGXN Client) ha una riga di comando di
cui sorvolo i dettagli implementativi, ma restando nel semplice ogni
subcommand è implementato da una classe che richiede certe opzioni:
anche solo questo con docopt non si può fare, la CLI è "monolitica", non
dinamica, e va generata in un solo punto.
Un pattern che invece uso molto sul lavoro, dove di script ne creo
tanti, è quello che mi serve spesso una coppia --quiet/--verbose che
vanno ad alterare il level di un logger, mi serve spesso una coppia
--start-date/--end-date che restituiscono oggetti date (prendendo sia
YYYY-MM-DD sia un numero di "giorni indietro" in modo da poter mettere
in un crontab --start-date 7 --end-date 1 per elaborare l'ultima
settimana), mi serve spesso un --dsn per settare il database dove
lavorare. Usando docopt dovrei ripetere in continuazione sia
l'impostazione della command line che il parsing delle opzioni ed
eventualmente farci qualcosa (es. impostare il level del logger). Con
optparse invece ho scritto delle funzioni che mi permettono di fare:
def parse_cmdline():
parser = optparse.OptionParser(usage=...)
parser.add_option("--roba-specifica-per-lo-script"...)
@script_utils.with_two_date(parser)
@script_utils.with_verbosity(parser)
@script_utils.with_dsn(parser)
def parse():
opt, args = parser.parse_args()
opt.files = args # per esempio
return opt
return parse()
Perché coi decoratori? Per la "doppia azione": quando il decoratore
viene applicato il parser viene popolato. Quando la funzione esce il
decoratore ha accesso ad opt e può verificare la validità dei valori, o
qualunque altra operazione (impostare una varabile globale...). Per
esempio questa è una delle implementazioni:
def with_verbosity(parser, logger_name=None):
"""Decorator to add --quiet and --verbose options to a script.
Takes an optional logger_name: if specified set the level on
that logger,
otherwise set it on the root logger.
Set the log level on WARNING if --quiet is specified, on DEBUG
if
--verbose is specified, on INFO if none is. Won't tell you what
happens if
you specify both: sod off, wise guy.
"""
def with_verbosity_(f):
@wraps(f)
def with_verbosity__(*args, **kwargs):
parser.add_option('--quiet', dest='loglevel',
default=logging.INFO,
action='store_const', const=logging.WARNING,
help="show less information")
parser.add_option('--verbose', dest='loglevel',
default=logging.INFO,
action='store_const', const=logging.DEBUG,
help="show more information")
opt = f(*args, **kwargs)
logging.getLogger(logger_name).setLevel(opt.loglevel)
return opt
return with_verbosity__
return with_verbosity_
Anche questo non si può fare con docopt: ad ogni script dovrei ripetere
le stesse dichiarazioni e le stesse operazioni.
--
Daniele Varrazzo - Develer S.r.l.
http://www.develer.com
Maggiori informazioni sulla lista
Python