2012-09-03 9 views
6

Ich verwende die Python-Bibliothek, Fabric, um einige Remote-Server-Wartung zu tun. Fabric gibt automatisch alle Antworten an entfernte und lokale Befehle aus, wenn Sie den Befehl nicht paarweise mit Anweisungen umbrechen. Wie so, auf einem lokalen Rechner,Was ist der pythonische Weg, um mehrere Funktionen in die gleiche mit Anweisungen zu wickeln

with settings(warn_only='true'): 
    with hide('running', 'stdout', 'stderr', 'warnings'): 
     output = local("uname -a", True) 

oder wie diese auf einem Remote-Rechner:

with settings(warn_only='true'): 
    with hide('running', 'stdout', 'stderr', 'warnings'): 
     output = run("uname -a") 

Ich bin eine lange und komplexe Aufgabe zu schreiben und finde mich diese beide mit Aussagen immer und immer wieder . Ich möchte eine Funktion namens _mute() schreiben, um diese Wiederholung zu verhindern. Es würde mir so etwas tun lassen:

def _mute(fabric_cmd, args): 
    with settings(warn_only='true'): 
     with hide('running', 'stdout', 'stderr', 'warnings'): 
      output = fabric_cmd(args) 
    return output 

def some_remote_task(): 
    # Run a remote task silently 
    _mute(remote, 'uname -a') 

def some_local_task(): 
    # Run a local task silently 
    _mute(local, 'uname -a', True) 

Ich habe in einige Lösungen gesucht und wissen, dass „eval“ könnte dies für mich tun. Aber jede Seite, die ich über eval gelesen habe, legt nahe, dass es aus Sicherheitsgründen fast immer eine schlechte Idee ist. Ich habe in Teiltöne geschaut, aber ich konnte nicht herausfinden, wie man ein Argument in meiner _mute-Funktion aufrufbar macht. Ich vermute, es gibt ein höheres Python-Konzept, das ich hier vermisse. Was ist der pythonische Weg, dies zu tun? Danke für jede mögliche Richtung, die du zur Verfügung stellen könntest.

Antwort

11

Die bessere Lösung wäre für Sie, Ihren eigenen Kontextmanager zu erstellen; bei weitem wäre der einfachste Weg, zu verwenden, um die contextlib.contextmanager decorator:

from contextlib import contextmanager 

@contextmanager 
def _mute(): 
    with settings(warn_only='true'): 
     with hide('running', 'stdout', 'stderr', 'warnings'): 
      yield 

Dann _mute als Kontext-Manager verwenden:

def some_remote_task(): 
    # Run a remote task silently 
    with _mute(): 
     output = remote("uname -a") 

Dieses viel kompakter ist und lesbar als mit den beiden größeren Kontext in das Feld eintragen Manager-Linien und hat die hinzugefügt Vorteil, dass Sie jetzt mehrere Befehle in diesem Kontext ausführen können.

Wie für Ihre Frage; Sie können ganz einfach beliebige Argumente für eine gegebene Funktion mit der *args Syntax anwenden:

def _mute(fabric_cmd, *args): 
    with settings(warn_only='true'): 
     with hide('running', 'stdout', 'stderr', 'warnings'): 
      return fabric_cmd(*args) 

def some_remote_task(): 
    # Run a remote task silently 
    output = _mute(remote, 'uname -a') 

Siehe *args and **kwargs? für weitere Informationen über das *args beliebige Argument listet Tricks.

+0

Dank der @contextmanager Dekorateur hat perfekt funktioniert. Ich weiß es zu schätzen, dass Sie mich sowohl für die Dokumente als auch für die * args-Syntax zu den Dokumenten geführt haben. –

Verwandte Themen