2016-01-19 10 views
5

Diciamo che ho alcuni dei futures:json.dump a concurrent.futures.Future()?

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

e alla fine voglio scaricare questi in JSON, e vi garantisco che i futures sono stati risolti da quel momento:

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

Come posso sposare i due ?

+0

Ho un hack che sovrascrive la classe 'jsonEncoder', ma forse esiste una soluzione migliore? –

risposta

4

Ignorare la classe JSONEncoder e chiamare o.result() su istanze Future è unidirezionale.

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) 

per farlo funzionare senza un personalizzato JSONEncoder, si potrebbe scorrere la struttura dei dati stessi, chiamando o.result():

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

o modificare data sul posto:

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

Penso che tu stia facendo un'ipotesi sulla rappresentazione del risultato in 'return o.result' - non ha bisogno di essere convogliato tramite' super(). Default() 'troppo? Infatti, forse è meglio chiamare in modo ricorsivo 'return self.default (o.result)' nel caso in cui 'result' sia un contenitore che ha un altro futuro risolto in esso? –

+0

Chiamate solo 'super(). Default()' per generare un 'TypeError': https://docs.python.org/2/library/json.html#json.JSONEncoder.default –

+0

Se' o.result() 'è un iterabile e lo si restituisce, dovrebbe comunque essere serializzato correttamente. Ho controllato il sorgente Python per assicurarmi che qualsiasi cosa restituito da 'default()' subisca il normale processo di serializzazione. –

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

Ottimo, ma presuppone la conoscenza del modello di dati nel sito di chiamata. Preferirei avere qualcosa di generico. –

+0

Creare una sottoclasse di Future basata su JSON? Probabilmente ha solo bisogno di scavalcare __str__ per chiamare 'self.result()'? – knite