2016-01-19 11 views
5

Sagen wir, ich habe einige Futures:json.dump eine gleichzeitige.futures.Future()?

f = concurrent.futures.Future() 
data = [f] 

Und schließlich möchte ich diese in JSON-Dump, und ich garantiere, dass Futures bis zu diesem Zeitpunkt aufgelöst wurden:

f.set_result(42) 
json.dumps(data) 

Wie kann ich die beiden heiraten ?

+0

Ich habe einen Hack, der die 'jsonEncoder' Klasse außer Kraft setzt, aber gibt es vielleicht eine bessere Lösung? –

Antwort

4

Das Überschreiben der JSONEncoder-Klasse und das Aufrufen von o.result() auf Future-Instanzen ist ein Weg.

class CustomJSONEncoder(json.JSONEncoder): 
    def default(self, o, *args, **kwargs): 
     if isinstance(o, concurrent.futures.Future): 
      return o.result() 
     return super(CustomJSONEncoder, self).default(o, *args, **kwargs) 

json.dumps(data, cls=CustomJSONEncoder) 

Um es ohne eine kundenspezifische JSONEncoder funktioniert, Sie durch die Datenstruktur selbst, ruft o.result() iterieren könnte:

data = [o.result() if isinstance(o, concurrent.futures.Future) else o for o in data] 

Oder data anstelle ändern:

for i, o in enumerate(data): 
    if isinstance(o, concurrent.futures.Future): 
     data[i] = o.result() 
+0

Ich denke, Sie machen eine Annahme über die Darstellung des Ergebnisses in 'return o.result' - muss das nicht durch 'super(). Purple()' auch? Vielleicht ist es am besten, rekursiv 'return self.default (o.result)' aufzurufen, falls 'result' ein Container ist, der eine andere aufgelöste Zukunft enthält? –

+0

Sie rufen nur 'super(). Default()' auf, um einen 'TypeError' zu erzeugen: https://docs.python.org/2/library/json.html#json.JSONEncoder.default –

+0

If' o.result() 'ist ein iteratable und Sie geben es zurück, es sollte noch ordnungsgemäß serialisiert werden. Ich habe die Python-Quelle überprüft, um sicherzustellen, dass alles, was von 'default()' zurückgegeben wird, den regulären Serialisierungsprozess durchläuft. –

0
json.dumps([d.result() for d in data]) 
+0

Großartig, aber das setzt Datenmodellwissen an der Call-Site voraus. Ich hätte lieber etwas Generisches. –

+0

Erstellen Sie eine JSON-fähige Unterklasse von Future? Muss wahrscheinlich nur __str__ überschreiben, um 'self.result()' aufzurufen? – knite