Topic: Python3.6+ - Requests asincrone  (Letto 649 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline bebo

  • python erectus
  • ***
  • Post: 231
  • Punti reputazione: 0
    • Mostra profilo
    • bebo_sudo's personal homepage
Python3.6+ - Requests asincrone
« il: Dicembre 19, 2017, 00:16 »
Buona serata ragazzi,
sto lavorando ad un progetto di analisi di crittovalute, e sto usando questa libreria (https://github.com/nlsdfnbch/bitex, ben fatta, a mio avviso.. lo sviluppatore e' in gamba, e lo sto anche aiutando a sviluppare alcune parti per rilasciare una versione 2.0) per interrogare vari exchange sui loro tassi di cambio: questa libreria funge da enorme wrapper sopra a requests, in modo da standardizzare, per quanto possibile, le diverse API delle decine di exchange disponibili.

Una chiamata di esempio e' (dopo un pip3 install --pre bitex):
>>> from bitex import Bitstamp
>>> resp = Bitstamp().ticker("btcusd")
>>> resp.json()
{'high': '19220.00', 'last': '18947.00', 'timestamp': '1513638591', 'bid': '18945.02', 'vwap': '18638.28', 'volume': '14935.03886224', 'low': '17835.20', 'ask
': '18947.00', 'open': '18953.00'}


La questione e' che ci sono parecchie di queste chiamate che vengono fatte ogni minuto per chiedere i prezzi di un centinaio di coppie, ed ovviamente vengono fatte in modo sequenziale. Finche' erano una decina, non era un grosso problema. Ma ora che sono tante, fare tante requests sequenzialmente ci mette piu' del minuto di intervallo di cui vorrei fare lo snapshot.

Cercando in rete ho trovato l'articolo di un tizio (https://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html) che tentava di far scalare python ad un milione di requests/minuto usando async: ho visto il codice che ha scritto e mi e' venuto male a vedere quegli async e await sparsi in giro.
Poi ho scoperto che esiste anche la libreria grequests (requests + getenv), requests-threads (che sembra essere un one-file), requests-futures, requests con twisted.

La mia domanda e', spero, semplice e banale: su Python 3.6* su Linux, nel 2017-ormai-2018, non esiste niente per fare requests asincrone, gia' integrato in requests o facilmente ottenibile? magari un parametro da passare nei kwargs di una chiamata a requests?
Si potrebbe risolvere con un map_async da multiprocessing? o qualcosa da multithreading? o sono una BEAST practice ("problemi ora due ho", semicit. Yoda e GlennHK) ?

Salutoni

*sarei disposto ad usare anche la 3.7 in beta, se ci fossero grandi vantaggi in questo campo

Offline GlennHK

  • python sapiens sapiens
  • ******
  • Post: 1.651
  • Punti reputazione: 1
    • Mostra profilo
    • La Tana di GlennHK
Re:Python3.6+ - Requests asincrone
« Risposta #1 il: Dicembre 19, 2017, 10:29 »
Per fare request asincrone temo di no. Io usai tempo fa aiohttp, devi solo capire concettualmente la programmazione concorrente.

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.869
  • Punti reputazione: 9
    • Mostra profilo
Re:Python3.6+ - Requests asincrone
« Risposta #2 il: Dicembre 19, 2017, 11:07 »
Mah, requests di per sé non è concurrent, tuttavia se la domanda è

> su Python 3.6* su Linux, nel 2017-ormai-2018, non esiste niente per fare requests asincrone,
> gia' integrato in requests o facilmente ottenibile?

ovviamente la risposta è sì, e te la sei già data da solo. Puoi tranquillamente usare requests-futures, anche se a quel che capisco in pratica sbatte request.get dentro un Executor, quindi è solo un piccolo wrap intorno a una sintassi del tipo

loop = asyncio.get_event_loop()
async def main():
    f1 = loop.run_in_executor(None, requests.get, 'www.foo.com')
    f2 = loop.run_in_executor(None, requests.get, 'www.bar.com')
    ...
    r1 = await f1
    r2 = await f2
    ...
loop.run_until_complete(main())

anche se da quel che mi sembra, requests-futures non usa la nuova sintassi con async e await.
A occhio direi che non ci vuole molto neanche a scriversi a mano gli async e await, lasciando perdere requests-futures, ma è una questione di gusti. Piuttosto c'è da dire che in sostanza Executor usa i thread dietro le quinte, quindi bisogna stare attenti ai soliti problemi coi thread... ma finché ti limiti a sbattere in un thread qualcosa come requests.get, non dovresti avere troppi problemi... in ogni caso  requests-futures in sostanza fa proprio questo, per il meglio o per il peggio.

Oppure naturalmente puoi buttar via requests (a malincuore) e usare invece aiohttp, che invece *è* concurrent, e quindi può essere usata tranquillamente con async e await (come anche dimostrato dall'articolo che hai linkato) senza usare un Executor dietro le quinte.

>  ho visto il codice che ha scritto e mi e' venuto male a vedere quegli async e await sparsi in giro.

E non capisco perché, ma insomma, vedi tu.

Offline bebo

  • python erectus
  • ***
  • Post: 231
  • Punti reputazione: 0
    • Mostra profilo
    • bebo_sudo's personal homepage
Re:Python3.6+ - Requests asincrone
« Risposta #3 il: Dicembre 19, 2017, 23:34 »
Citazione da: GlennHK
devi solo capire concettualmente la programmazione concorrente
su quella ci sono abbastanza, purtroppo ho dovuto lavorare con un po' di js con angular recentemente

Citazione da: RicPol
>  ho visto il codice che ha scritto e mi e' venuto male a vedere quegli async e await sparsi in giro.

E non capisco perché, ma insomma, vedi tu.
Ma si, niente, e' semplicemente strano vedere per la prima volta questi "cosi" in mezzo a del codice python.


Mi vado ad imparare un po' di async va', perche' non mi va di buttare via una libreria gia' fatta, funzionante e testata, che fa esattamente quello che serve a me.

Buone feste ragazzi!

Offline GlennHK

  • python sapiens sapiens
  • ******
  • Post: 1.651
  • Punti reputazione: 1
    • Mostra profilo
    • La Tana di GlennHK
Re:Python3.6+ - Requests asincrone
« Risposta #4 il: Dicembre 20, 2017, 00:17 »
su quella ci sono abbastanza, purtroppo ho dovuto lavorare con un po' di js con angular recentemente

Mmm, non parlo di codice a callback, eh.
Per intenderci, alla fine il tutto regge su una roba simile a quella. Mai sentito parlare di reactor pattern?

In sostanza si tratta (molto grossolanamente, eh) di trasformare:


async def f():
    val = await do_operation()
    do_more(val)


in


def f():
    do_operation_1(lambda val: do_more(val))


dove do_operation_1 chiama una callback quando termina l'operazione (e nota, ho volutamente usato lambda e non il parametro con funzione).

Aggiungi poi che le varie funzioni async (coroutines) vengono schedulate da un MainLoop, e hai la base di asyncio.

Offline bebo

  • python erectus
  • ***
  • Post: 231
  • Punti reputazione: 0
    • Mostra profilo
    • bebo_sudo's personal homepage
Re:Python3.6+ - Requests asincrone
« Risposta #5 il: Dicembre 20, 2017, 00:53 »
Ok ok, mi e' abbastanza chiaro. Casomai avessi altri dubbi esistenziali, mi faro' risentire.
"practice makes perfect" ;)

Offline Python

  • python sapiens sapiens
  • ******
  • Post: 2.045
  • Punti reputazione: 2
  • Radon - Cyclomatic Complexity of your Python code
    • Mostra profilo
    • Radon - Cyclomatic Complexity of your Python code
Re:Python3.6+ - Requests asincrone
« Risposta #6 il: Dicembre 20, 2017, 09:05 »
Non credo che Bitstamp sia d'accordo con milioni di richieste al minuto.

Non ho mai usato l'API di Bitstamp, ma so che alcuni degli exchange più professionali, come GDAX, offrono API websocket. In quel modo puoi tenerti aggiornato in tempo reale sul prezzo dell'ultima trade o addirituttura mantere una rappresentazione real time dell'order book (come fa CryptoWatch per esempio).

Per uno script molto più semplice invece, io avevo risolto il problema (che è IO-bound) usando semplicemente concurrent.futures.ThreadPoolExecutor. Funzionava benissimo, ma era una cosa quick 'n dirty senza testing né altro.

Offline riko

  • python deus
  • *
  • moderatore
  • Post: 7.453
  • Punti reputazione: 12
    • Mostra profilo
    • RiK0 Tech Temple
Re:Python3.6+ - Requests asincrone
« Risposta #7 il: Dicembre 20, 2017, 13:31 »
Ora parliamo vuoi? Non e' colpa tua, ma non trovi insolito che per un linguaggio "semplice" come Python tu debba chiedere su un forum come fare?
E nota, non e' colpa tua, anticipo. In Go e perfino in Java la soluzione sarebbe stata completamente ovvia.

In Python, no. Nel senso che *finalmente* hanno messo una soluzione per concorrenza I/O scalabile nella libreria standard. Come Go e come Java. Solo che mentre la soluzione di Go non e' veramente opinionata (ti da tutto quello che serve con una manciata di primitive piuttosto naturali), quella di Python e' *molto* opinionata. In fatti di primo acchito non e' che ti sia piaciuta tanto. Nemmeno a me. Specialmente perche' asyncio ha cambiato il modo di fare le cose due o tre volte almeno (ho seguito molto in distanza). So much for "only one way to do it". Tipo per leggere il codice di librerie che usano asyncio devi probabilmente conoscerli *tutti* a seconda della compatibilita' e dell'eta' della libreria. Grazie. Lessi pezzi random della libreria standard di go, anche quelli piu' impestati, dopo *3* giorni che avevo aperto il tutorial di Go e ben prima di riuscire a scrivere codice Go idiomatico... direi anche prima di scrivere codice vagamente presentabile in Go. Che era quello che mi era piaciuto in Python 2.2.

Ma alla fine... usa asyncio. Resistance is futile. Python e' stato a lungo uno dei migliori linguaggi per fare I/O massiccio. Twisted, con tutti i suoi difetti, era molto robusto ed efficace (ed anche molto opinionato, ma almeno era Python "standard").
Poi mi sono innamorato di gevent (grequests e' un wrapperino -- o era -- che metteva insieme gevent e requests).  Non opinionated, efficace, efficient. Semplice. Solo che... robusto? Se hai controllo completo delle tue dipendenze e scrivi un'applicazione, si. Se invece scrivi una libreria, no.

Nel frattempo sono passati gli anni. Go ha mostrato come si fanno le cose. Java ha fatto passi da gigante. C++ anche. Ed e' uscito asyncio. Too little, too late. E lo hanno cambiato ventiquattro volte. Pero' *almeno* risolve il dramma esistenziale della concorrenza in Python. Siccome non esiste(va) una soluzione standard e ovvia, non potevi inserire il modello di concorrenza nella tua libreria. La tua libreria deve essere single tutto. Che specie se hai tante API call potrebbe non essere davvero fattibile.Oppure devi complicare considerevolmente l'architettura per dare modo agli utenti della libreria di innestarla nel loro sistema di concorrenza. O, come ultima opzione, puoi semplicemente legarti ad un sistema di concorrenza e chi ne usa un altro si arrangia (in generale se in Python mischi processi, thread, gevent, twisted e compagnia fai un macello... ci sono modi "safe" di integrarli a coppie, in generale, ma non e' una cosa completamente generale e bisogna pensare molto a quello che si sta facendo).

Quindi io *spero* che se anche non mi piace, asyncio prenda pieda a sufficienza che "tutti" usino asyncio e che le librerie che ne hanno bisogno usino anche loro asyncio. A questo punto anche chi volesse usare un aggeggio diverso, potrebbe trovarsi l'integrazione gia' fatta da quelli che scrivono suddetto oggetto. Per esempio anche se i thread non piacciono a nessuno, siccome sono nella lirberia standard gevent e Twisted hanno modi di integrarsi in un sistema mulltithread (specificamente, gevent "patcha" i thread dietro le quinte e li fa diventare i sui thread e poi si capisce... a volte questa cosa esplode spettacolarmente -- a seconda di come e' fatta la libreria --, ma in generale ce ne si esce; Twisted invece ha dei normali oggetti... e usa esso stesso Thread dietro le quinte per certe cose e quando ha senso. Che poi e' un problema in tutti i sistemi che cercano di darti il modello di posix... che e' noto per avere problemi nell'integrare thread e processi.

Offline bebo

  • python erectus
  • ***
  • Post: 231
  • Punti reputazione: 0
    • Mostra profilo
    • bebo_sudo's personal homepage
Re:Python3.6+ - Requests asincrone
« Risposta #8 il: Dicembre 20, 2017, 14:52 »
Citazione
Non credo che Bitstamp sia d'accordo con milioni di richieste al minuto.
Se forniscono un servizio aperto al pubblico, penso siano problemi loro imparare a tenerlo in piedi. Inoltre, non so se ti e' sfuggito, faccio una decina di richieste ad una decina di exchange, una volta al minuto (temporizzato con un ottimo APScheduler con blocking scheduler).

Citazione
Non ho mai usato l'API di Bitstamp, ma so che alcuni degli exchange più professionali, come GDAX, offrono API websocket. In quel modo puoi tenerti aggiornato in tempo reale sul prezzo dell'ultima trade ...
Ed in teoria ci sono gia' anche integrati nella libreria `bitex` che sto usando. A me non serve il prezzo in tempo reale (o perlomeno non in questo momento), e sarebbe anzi molto piu' complicato. Per ora sto collezionando dati su cui applicare modelli predittivi.

Citazione
Per uno script molto più semplice invece, io avevo risolto il problema (che è IO-bound) usando semplicemente concurrent.futures.ThreadPoolExecutor. Funzionava benissimo, ma era una cosa quick 'n dirty senza testing né altro.
Grazie della dritta @Python. Il fatto e' che non mi va molto di stare ad impararmi come parlare con le API di una ventina di exchange diversi, e usare questa libreria gia' fatta mi risparmierebbe un sacco di tempo.

Citazione
Ora parliamo vuoi? Non e' colpa tua, ma non trovi insolito che per un linguaggio "semplice" come Python tu debba chiedere su un forum come fare?
E nota, non e' colpa tua, anticipo. In Go e perfino in Java la soluzione sarebbe stata completamente ovvia.
Ciao Enrico.. Si, immaginavo che in altri linguaggi non ci sia tutto sto casino che c'e' in python per fare cose asincrone.

Citazione
Ma alla fine... usa asyncio. Resistance is futile.
Il lato oscuro della forza e' molto potente...

Citazione
Poi mi sono innamorato di gevent [...] Solo che... robusto? Se hai controllo completo delle tue dipendenze e scrivi un'applicazione, si. Se invece scrivi una libreria, no.
Mah, forse per me andrebbe anche bene, in quanto sto scrivendo una (semplice) applicazione.

Provo a confrontare un po' async/await e la libreria asyncio, grazie ancora del prezioso confronto intanto.

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.869
  • Punti reputazione: 9
    • Mostra profilo
Re:Python3.6+ - Requests asincrone
« Risposta #9 il: Dicembre 20, 2017, 16:19 »
> Si, immaginavo che in altri linguaggi non ci sia tutto sto casino che c'e' in python per fare cose asincrone.
> Il lato oscuro della forza

Mah, insomma, adesso non esageriamo nemmeno però. Se l'op trova complicato scrivere async e await sulla tastiera, meno male che non programma in c#.

Ora, nel mio piccolo dò ragione a Riko, però... però. E' sicuramente vero che "il modo giusto" per fare cose asincrone in python è più contorto che in Go, per dire. Anche perché in python tutta questa parte è stata innestata, e per giunta in un momento storico in cui la comunità era già rimasta abbastanza bruciata dalla pessima reazione a py3, per aver voglia di stravolgere il linguaggio ancora una volta. Così hanno iniziato con un semplice ritocco alla sintassi di yield (ovvero yield from, in py3.3) e l'hanno usato come minima variante al linguaggio indispensabile, e si sono subito buttati su una libreria (asyncio, py3.4) senza più modificare il linguggio. Ma alla fine questa cosa di asyncio non è sembrata sufficiente, e sono giustamente tornati a toccare il linguaggio con async e await (py3.5).
Ora, sicuramente questa crescita "organica" e un po' disordinata non ha aiutato la gente a capirci granché, e soprattutto non è riuscita a stabilizzare un "modo corretto" di fare le cose asincrone in python. Adesso però la situazione sembra molto più stabile, e probabilmente anche più chiara. Nel frattempo è uscito python 3.6, che ha introdotto altri ritocchi in asyncio, ma non ha più toccato il linguaggio. Direi che la polvere si sta posando.

E adesso che si è posata la polvere, la cosa importante da capire mi sembra questa: async e await d'ora in poi *sono* le API asincrone di Python. Tuttavia async e await non sono legate a un event loop specifico (questo può anche non piacere come design, ovviamente. Ma è Python... in questo non è opinionated): ovviamente si suppone che la cosa naturale sia usare asyncio, ma non è necessario. La cosa sbagliata (ma comprensibile, vista la storia fin qui), è pensare ad asyncio come il modo di fare le cose asincrone, e async/await come degli shortcut per asyncio.
Tutto questo e altro ancora, è spiegato secondo me molto bene in questo articolo di Brett Cannon, che consiglio all'OP di leggere come prima cosa: https://snarky.ca/how-the-heck-does-async-await-work-in-python-3-5/.
Dopo di che, uno è liberissimo di non "capire" asyncio (come Armin Ronacher, altro articolo che consiglio: http://lucumr.pocoo.org/2016/10/30/i-dont-understand-asyncio/).
Uno è libero anche di detestare asyncio e caricarlo di miseria, come questo recente e ormai famigerato articolo: https://veriny.tf/asyncio-a-dumpster-fire-of-bad-design/.
Ma resta che asyncio è "libreria standard", non "linguaggio". Per dire, l'autrice di quest'ultimo articolo odia asyncio con tutte le sue forze: benissimo, può scegliere di usare async/await pescando invece il loop di Curio https://github.com/dabeaz/curio, come appunto fa lei. E' un po' come dire, capisco che uno possa odiare httplib, ma chi ti impedisce di usare requests.

In tutto questo, credo poi che un problema enorme sia che non ci sono ancora librerie asincrone "celebri" e stabili, che aiutano la gente a instradarsi verso un modo standard di procedere. Ed è anche comprensibile che non ci siano, visto che finora le api sono state molto ballerine. C'è Curio, e (in un altro contesto) c'è aiohttp. Ma poco altro. Per dire, se Kennet Reitz si prendesse un mese di tempo per riscrivere requests in modo asincrono, credo che in capo a un anno tutti useremmo requests con async e await senza neache pensarci più. Purtroppo, pare che questo non accadrà tanto presto: https://github.com/requests/requests/issues/2801. E come si vede, non per colpa di requests, ma per colpa di httplib che a sua volta non è asincrona. E quindi in definitiva, credo che il progresso nel prossimo futuro sarà di rendere in primo luogo asincrona la libreria standard... mentre ovviamente si migliora via via l'api di asyncio. Avevo letto qualcosa in merito, ma adesso non trovo più il link...

« Ultima modifica: Dicembre 20, 2017, 16:21 da RicPol »

Offline bebo

  • python erectus
  • ***
  • Post: 231
  • Punti reputazione: 0
    • Mostra profilo
    • bebo_sudo's personal homepage
Re:Python3.6+ - Requests asincrone
« Risposta #10 il: Dicembre 26, 2017, 00:43 »
> > Si, immaginavo che in altri linguaggi non ci sia tutto sto casino che c'e' in python per fare cose asincrone.
> > Il lato oscuro della forza
>
> Mah, insomma, adesso non esageriamo nemmeno però. Se l'op trova complicato scrivere async e await sulla tastiera, meno male che non programma in c#.

Suvvia RicPol, un po' di ironia ;-)


> async e await non sono legate a un event loop specifico

Ecco, questo concetto mi mancava ancora. Avevo capito, erroneamente, che async/await fossero un'alternativa a asyncio, ed invece le prime due keyword devono appoggiarsi ad un event loop esterno, che sia asyncio/curio/etc.

Ho letto l'articolo di Brett Cannon, ma non e' molto utile come introduzione, va troppo nei dettagli.
Ho invece trovato questo blog post di Michael Driscoll http://www.blog.pythonlibrary.org/2016/07/26/python-3-an-intro-to-asyncio/ molto piu' terra terra con degli esempietti pratici, cosa che invece non ho trovato nella doc ufficiale di asyncio, che e' solamente reference degli oggetti presenti in asyncio.

Ho poi provato ad implementare un tentativo (sembra funzionante) di requests asincrone tramite asyncio, usando questa risposta di SO ed adattandola con functools. La risposta su SO usa il metodo run_in_executor() sul loop, che di default (se None viene passato come executor) usa un ThreadPoolExecutor.
Questo e' il mio tentativo, e sembra funzionare per le due coppie di currencies che ho testato:

import asyncio
import requests
import time
import functools
import decimal

from bitex import (Kraken, Bitstamp, Gemini, Bittrex, GDAX, RockTradingLtd,
                   Poloniex)

def ticker(exchange_instance, pair):
    return exchange_instance.ticker(pair)

async def main():
    loop = asyncio.get_event_loop()
    start = time.time()
    future1 = loop.run_in_executor(None, functools.partial(ticker, Bitstamp(), "btcusd"))
    future2 = loop.run_in_executor(None, functools.partial(ticker, Bitfinex(), "btcusd"))
    response1 = await future1
    response2 = await future2
    print(response1.json(parse_int=decimal.Decimal,
                         parse_float=decimal.Decimal))
    print(response2.json(parse_int=decimal.Decimal,
                         parse_float=decimal.Decimal))
    print("tot", time.time() - start)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())



  • Prima domanda: come idea e' brutta? e' tanto male usare run_in_executor per "sbloccare" le chiamate bloccanti di requests (nascoste dietro alla libreria bitex che sto usando)? Volendo restare saldi alla libreria bitex che sto usando, che usa requests e quindi bloccante, e' meglio lasciar perdere async e usare un ThreadPoolExecutor(N), con N numero di chiamate che devo fare ( (che e' un valore noto e costante a runtime)?
  • Seconda domanda, valida se la prima ha senso: come si generalizza ora? si puo' mettere un await [lista di futures]?
    Questo perche' ho tante coppie:

    exchange_to_currencies = {
        "kraken":
        (Kraken(),
         ("XBTUSD", "XBTEUR", "XBTJPY", "BCHEUR", "BCHUSD", "BCHXBT", "DASHEUR",
            "DASHUSD", "DASHXBT", "EOSXBT", "ETHEUR", "ETHJPY", "ETHUSD", "ICNXBT",
            "LTCXBT", "LTCEUR", "LTCUSD", "MLNXBT", "REPXBT", "REPEUR", "XLMXBT",
            "XMRXBT", "XMREUR", "XMRUSD", "XRPXBT", "XRPEUR")),

        "bitstamp":
        (Bitstamp(),
         ("btcusd", "btceur", "xrpusd", "xrpeur", "xrpbtc", "ltcusd", "ltceur",
          "ltcbtc", "ethusd", "etheur", "ethbtc", "bchusd", "bcheur", "bchbtc")),

        "gdax":
        (GDAX(),
         ("BTC-USD", "BTC-EUR", "ETH-USD", "ETH-EUR", "ETH-BTC", "LTC-USD",
          "LTC-EUR", "LTC-BTC")),
    ...
    }

    e vorrei avere una "struttura" di futures su cui applicare una callback una volta ritornate.


Grazie ancora ragazzi, e buone feste!
« Ultima modifica: Dicembre 26, 2017, 00:59 da bebo »

Offline GlennHK

  • python sapiens sapiens
  • ******
  • Post: 1.651
  • Punti reputazione: 1
    • Mostra profilo
    • La Tana di GlennHK
Re:Python3.6+ - Requests asincrone
« Risposta #11 il: Dicembre 27, 2017, 14:17 »
1. Secondo me stai nascondendo la polvere sotto il tappeto usando un ThreadPoolExecutor, non fai vero I/O asincrono. E se non è supportato a basso livello dalla libreria ci puoi fare ben poco.
2. Vuoi qualcosa come asyncio.gather?

Offline bebo

  • python erectus
  • ***
  • Post: 231
  • Punti reputazione: 0
    • Mostra profilo
    • bebo_sudo's personal homepage
Re:Python3.6+ - Requests asincrone
« Risposta #12 il: Dicembre 27, 2017, 22:58 »
  • Mi rendo conto che non e' una soluzione ottimale, e che anzi e' un po' sporca. E so che non e' il massimo, per pulizia e chiarezza del codice, e per performance, ma l'alternativa sarebbe riscrivermi tutti i wrapper della libreria in modo asincrono, un lavoro da una settimana intera.
  • Adesso mi guardo un po' meglio asyncio e i vari metodi, grazie per la dritta GlennHK.

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.869
  • Punti reputazione: 9
    • Mostra profilo
Re:Python3.6+ - Requests asincrone
« Risposta #13 il: Dicembre 28, 2017, 08:10 »
> Mi rendo conto che non e' una soluzione ottimale, ...

Mah, vedi tu... in realtà questo sarebbe il lavoro da fare... il codice è asincrono dalla radice, oppure non lo è. Non basta aggiungere asycncio/async/await in cima per renderlo asincrono. Ora, nel tuo caso se ho ben capito basterebbe sostituire request con le chiamate quasi uguali di aiohttp... come minimo ci investirei un paio d'ore a studiare la fattibilità della cosa.

Offline Python

  • python sapiens sapiens
  • ******
  • Post: 2.045
  • Punti reputazione: 2
  • Radon - Cyclomatic Complexity of your Python code
    • Mostra profilo
    • Radon - Cyclomatic Complexity of your Python code
Re:Python3.6+ - Requests asincrone
« Risposta #14 il: Dicembre 28, 2017, 19:13 »
Mi rendo conto che non e' una soluzione ottimale, e che anzi e' un po' sporca. E so che non e' il massimo, per pulizia e chiarezza del codice, e per performance, ma l'alternativa sarebbe riscrivermi tutti i wrapper della libreria in modo asincrono, un lavoro da una settimana intera.

Ho guardato il codice di bitex in maniera decisamente sommaria, e mi sembra che ogni exchange abbia un interfaccia dedicata. Credo che quindi ti basti sostituire solo le classi ExchangeNameREST per ogni exchange. Se poi sei interessato a un sottoinsieme di quelli disponibili, il lavoro è ancora più veloce.