Domanda

Ho riflettuto su questo troppo a lungo e non hanno ottenuto alcuna idea, forse qualcuno di voi può aiutare.

Ho una cartella di script Python, i quali hanno lo stesso corpo circostante (letteralmente, ho generato da uno script di shell), ma hanno un pezzo che è diverso da tutti loro. In altre parole:

Top piece of code (always the same)
Middle piece of code (changes from file to file)
Bottom piece of code (always the same)

E mi sono reso conto oggi che questa è una cattiva idea, per esempio, se voglio cambiare qualcosa dall'alto o sezioni inferiori, ho bisogno di scrivere uno script di shell per farlo. (Non che questo è difficile, sembra proprio come è molto cattivo codice di saggio).

Quindi quello che voglio fare, è avere uno script python esterna che è come questo:

Top piece of code
Dynamic function that calls the middle piece of code (based on a parameter)
Bottom piece of code

E poi tutti gli altri file nella cartella python può essere semplicemente il pezzo centrale di codice. Tuttavia, modulo normale non avrebbe funzionato qui (a meno che non mi sbaglio), perché vorrei ottenere il codice ho bisogno di eseguire dal farvi riflettere, il che sarebbe una stringa, e quindi non saprei quale funzione da eseguire fino al runtime .

Così ho pensato su più di due soluzioni:

  1. Potrei scrivere un mucchio di istruzioni if, uno per eseguire ogni script sulla base di un certo parametro. Ho rifiutato questo, in quanto è ancora peggio del progetto precedente.
  2. ho potuto utilizzare:

    os.command (sys.argv [0] scriptName.py)

    che eseguire lo script, ma chiamando pitone alla chiamata python non sembra molto elegante per me.

Quindi, qualcuno ha altre idee? Grazie.

È stato utile?

Soluzione

Se si conosce il nome della funzione come una stringa e il nome del modulo come una stringa, allora si può fare

mod = __import__(module_name)
fn = getattr(mod, fn_name)
fn()

Altri suggerimenti

Un'altra possibile soluzione è quella di avere ognuno dei tuoi file ripetitivi importare la funzionalità dal file principale

from topAndBottom import top, bottom
top()
# do middle stuff
bottom()

In aggiunta alle varie risposte già postato, si consideri la Template Method modello di progettazione: fare una classe astratta come

class Base(object):
    def top(self): ...
    def bottom(self): ...
    def middle(self): raise NotImplementedError
    def doit(self):
        self.top()
        self.middle()
        self.bottom()

Ogni modulo pluggable poi fa una classe che eredita da questo Base e deve avere la priorità middle con il relativo codice.

Forse non garantito per questo caso semplice (non ancora bisogno di importare il modulo giusto per istanziare la sua classe e chiamata doit su di esso), ma comunque vale la pena tenere in mente (insieme alle sue numerose varianti divinatorio, che ho ampiamente spiegato in numerosi colloqui tecnologia ora disponibile su youtube) per i casi in cui il numero o la complessità di "pezzi pluggable" continua a crescere - Template Method (nonostante il suo nome orrido ;-) è un modello solido, ben collaudato e altamente scalabile [[ a volte un po 'troppo rigida, ma questo è esattamente quello che mi rivolgo a quei molti colloqui di tecnologia - e questo problema non si applica a questo specifico caso d'uso]]

.
  

Tuttavia, il modulo normale sarebbe non lavorare qui (a meno che non mi sbaglio), perché vorrei ottenere il codice ho bisogno di eseguire dal farvi riflettere, il che sarebbe una stringa, e quindi non saprei quale funzione di aperta fino al tempo di esecuzione.

Si lavorerà bene - uso __import__ incorporata o, se si hanno layout molto complessi, imp modulo di importare lo script. E allora si può ottenere la funzione module.__dict__[funcname] per esempio.

L'importazione di un modulo (come spiegato in altre risposte) è sicuramente il modo più pulito per fare questo, ma se per qualche motivo che non funziona, a patto che non si sta facendo nulla di troppo strano è possibile utilizzare exec . Si corre in sostanza il contenuto di un altro file come se fosse incluso nel file corrente nel punto in cui è chiamato exec. E 'la cosa più vicina Python ha una dichiarazione source del genere inclusi in molte conchiglie. Come minimo, qualcosa di simile a questo dovrebbe funzionare:

exec(open(filename).read(None))

Che ne dici di questo?

function do_thing_one():
   pass

function do_thing_two():
   pass

dispatch = { "one" : do_thing_one,
             "two" : do_thing_two,
           }

# do something to get your string from the command line (optparse, argv, whatever)
# and put it in variable "mystring"

# do top thing
f = dispatch[mystring]
f()
# do bottom thing
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top