Come gestire la configurazione dei moduli Python, specialmente se usati standalone e in framework come Django

3

Sto cercando di impacchettare un modulo Python per pip, seguendo la guida qui .

Un'area su cui vorrei ricevere un feedback è le best practice o le convenzioni per rendere configurabile il mio modulo. Il modulo è una libreria per comunicare con i servizi RESTful federati / datastore locali e lo usiamo sia come libreria da riga di comando che come app di Django. Quindi mi piacerebbe che fosse configurabile manualmente e configurabile dal file settings.py di Django.

Il nostro metodo attuale è orribile: fa affidamento su una serie di file settings.py all'interno della libreria, che vengono sovrascritti ogni volta che eseguiamo il pull da git, non modificabili durante il runtime, ecc.

La mia idea di soluzione è racchiudere l'intera libreria nella sua classe e, nel metodo __init__ , fare qualcosa del tipo:

try:
    from django.conf import settings
    self._remote_host = settings.REMOTE_HOST
except:
    self._remote_host = DEFAULT_HOST

Ma sembra che si occupi solo di Django e sembra complicato - e se qualcuno volesse usare la nostra libreria con Flask o qualcos'altro? C'è un modo più universale per rendere un modulo Python configurabile da strumenti esterni e avere un valore predefinito? O è una causa persa, e dovrei limitarmi alla configurazione su init via argomenti?

    
posta user 14.11.2014 - 21:17
fonte

2 risposte

3

Ci sono due problemi che si incontrano qui:

  1. Il tuo pacchetto è un singleton sebbene esistano molte configurazioni diverse.
  2. Dove memorizzare i dati e come migrare - quale database utilizzare.

Singleton

Ho fatto un progetto divertente con molti moduli che dovevano essere configurati da soli. Il progetto intendeva eseguire una volta per computer .

L'alternativa è mettere tutto in classi e istanziarli con una configurazione. Tist consentirebbe l'esistenza di molte configurazioni differenti all'interno di un programma. Quando potresti aver bisogno di questo, dovresti ristrutturare l'intero codice.

database

Forse il tuo progetto è per un'azienda e deve essere sviluppato per un tempo più lungo e la configurazione non deve essere buttata via. Quindi potrebbe essere necessario tenere a mente molte configurazioni precedenti quando si modificano i valori predefiniti e si aggiorna la configurazione. Database adeguati hanno risolto il problema.

La mia soluzione di compromesso

Nel mio caso

  • La configurazione può essere eliminata se il mio modello cambia.
  • Il pacchetto viene eseguito non solo una volta per processo ma anche una volta per computer.
  • Solo un thread accede alla configurazione.

Esiste un modulo chiamato config.py con i seguenti metodi:

import config
config.load()
config.save()

Lo usi come questo (Esempio 1):

config.load()
config.my_value = 'test'
config.save()

C'è anche un file chiamato constants.py che dovrebbe essere meglio chiamato% codice%. Ha le funzioni

import constants
constants.default_configuration()
constants.config_file_name() # where to store the config data

E per (Esempio1) il constants.py dovrebbe assomigliare a questo:

def default_configuration():
    return {'my_value' : 'default'} # to avoid attribute errors

Il modulo config salva e carica la configurazione usando pickle. Se non viene trovata alcuna configurazione per una variabile, viene utilizzata la configurazione predefinita.

Avrai bisogno di uno stile di codifica che recuperi sempre la configurazione da config.py. Non deve essere memorizzato in una variabile locale o in un attributo per un periodo di tempo prolungato poiché può cambiare.

La mia versione precedente si chiama runningConfiguration . Non ha carico esplicito e non ha anche alcun attributo predefinito.

    
risposta data 15.11.2014 - 10:48
fonte
2

TL; DR: passa come args in init. Bilancia l'uso delle librerie contro il fattore limitante che possono rappresentare per gli altri che non usano quelle librerie e non vogliono farlo.

C'è una regola generale che esiste una correlazione inversa tra le librerie di numeri utilizzate da un progetto (specialmente quelle che dettano criteri come config o db) e la popolazione di persone che possono / vogliono usare la tua libreria.

Ad esempio, se crei una libreria che funziona solo con Django, ti limiti ai soli utenti di Django. Lo stesso con la configurazione, il database specifico, ecc.

Le librerie dipendenti che non dettano criteri non hanno un impatto significativo, ma ciò non significa che non ci sia alcun impatto. I motivi per non voler usare questo tipo di librerie dipendenti probabilmente eseguiranno il gioco d'azzardo:

  • riduzione al minimo delle dimensioni del programma (a torto oa ragione questo può essere un motivo)
  • problemi di sicurezza
  • problemi di conformità
  • deve usare un'altra libreria dipendente che confligge
  • deve utilizzare una versione diversa della libreria dipendente
  • etc

Per queste ragioni ti suggerisco di andare sempre con la dipendenza minima da altre librerie. In questo caso significherebbe passare gli argomenti in init e consentire al consumatore della tua libreria di decidere come e quale configurazione si desidera utilizzare.

    
risposta data 16.11.2014 - 09:20
fonte

Leggi altre domande sui tag