Home

PythonAppTemplate

dev python

Introduzione

Spesso capita di dover implemetare un applicazione a linea di comando in tempi molto rapidi, quello che segue è un esempio di codice di partenza; questo template risponde all’esigienza di disporre in breve tempo di un implemetazione flessibile ed estensibile.

Il codice è pubblicco ed è disponibile su github

Template

In generale quando bisogna scrivere un applicazione a linea di comando serve:

Questo template cerca di rispondere a tutti i punti precedenti.

Struttura

Files presenti nel progetto

$ tree
.
├── app # questo file contiene il main dell'applicazione
├── app_modules
│ ├── commands
│ │ ├── commandline_parser.py # parser della linea di comando
│ │ ├── command.py # classe base per gestire i comandi
│ │ ├── __init__.py
│ │ ├── runner
│ │ │ ├── __init__.py
│ │ │ └── run_version.py # esempio di comando che stampa la versione
│ │ └── setter
│ │ ├── __init__.py
│ │ ├── set_conf.py
│ │ └── set_env.py
│ ├── core
│ │ ├── config.py
│ │ ├── constants.py
│ │ ├── __init__.py
│ │ └── mlogger.py
│ └── __init__.py
├── build.sh
├── LICENSE
├── README.md
└── requirements.txt

5 directories, 18 files

Diagramma di flusso delle classi

Durante l’esecuzione l’applicazione seguirà i seguenti passi:

diagramma di flusso

  1. la classe app inizia l’esecuzione e prepara il logger
  2. la classe app instanzia la classe commandline_parser
  3. la classe commandline_parser inizializza tutti i comandi
  4. la classe commandline_parser analizza gli argomenti passati da linea e costruisce l’elenco dei comandi da eseguire
  5. la classe commandline_parse ritorna alla classe app l’elenco dei comandi
  6. la classe app esegue tutti i comandi gestendo eventuali eccezzioni

Estendere il template

Per estendere il template bisognerà per prima cosa inserire i codici specifici dell’applicazione dentro la cartella app_module, e poi iniziare a creare i nuovi comandi.

I comandi vengono distinit in :

Esempio di nuovo comando

Supponiamo di voler creare l’opzione --say-hello, bisognerà creare il file :

app_modules/commands/runner/sey_hello.py

from app_modules.core import LoggerFactory
from app_modules.core import SingleConfig
from app_modules.core import AppConstants
from app_modules.commands.command import Command

class Say_hello ( Command ):
    short_arg = None
    long_arg = 'say-hello'
    cmd_help = 'print hello world'
    cmd_type = None
    cmd_action = 'store_true'

    def __init__ ( self, param = None ):
        super(). __init__ ()
        self.logger = LoggerFactory.getLogger( str( self. __class__ ))

    def run( self ):
        print('hello world')

successivamente è necessario aggiornare il file

app_modules/commands/runner/ __init__.py

in maniera che il nuovo comando sia richiamabile:

__all__ = [
    'Run_version',
    'Say_hello' 
    ]

# deprecated to keep older scripts who import this from breaking
from app_modules.commands.runner.run_version import Run_version
from app_modules.commands.runner.say_hello import Say_hello

A questo punto è necessario registrare nel parser il nuovo comando :

# file app_modules/commands/commandline_parser.py
# linea 38

        self.rcl = [ 
            Run_version,
            Say_hello
            ]

Infine è possibile provare il nuovo comando:

$ python app -h
usage: App [-h] [--version] [--say-hello] [--conf CONF]

A sample python app

optional arguments:
  -h, --help show this help message and exit
  --version, -V print version
  --say-hello print hello world
  --conf CONF, -c CONF pass a configuration file
 
$ python app --say-hello
hello world

Conclusine

Il codice dell’esempio è disponibile sul branch hello-world.

Invito tutti a forcare il mio codice per migliorarlo o fornirmi un feedback sulle scelte fatte.

Riferimenti