2013-04-12 4 views
11

Di recente ho lavorato su un progetto di pet in pitone con pallone. Si tratta di un semplice pastebin con supporto per l'evidenziazione della sintassi sul lato server con pygments. Poiché si tratta di un'attività costosa, ho delegato l'evidenziazione della sintassi a una coda delle attività di sedici e nel gestore richieste che aspetto che finisca. Inutile dire che questo non fa altro che alleviare l'utilizzo della CPU a un altro lavoratore, perché l'attesa di un risultato blocca ancora la connessione al server web. Nonostante il mio istinto mi dice di evitare l'ottimizzazione prematura come la peste, ho ancora potuto non mi aiuterà a curiosare dentro asincrona.Attività asincrone e CPU associate a Python?

Async

Se hanno seguito pitone sviluppo web negli ultimi tempi, sicuramente avete visto che asincrona è ovunque. Ciò che async fa è ricondurre il multitasking cooperativo, il che significa che ogni "filo" decide quando e dove cedere a un altro. Questo processo non preemptive è più efficiente dei thread OS, ma ha ancora gli svantaggi. Per il momento non sembrano essere 2 approcci principali:

  • evento di stile/callback multitasking
  • coroutine

La prima prevede concorrenza attraverso componenti debolmente accoppiati eseguite in un ciclo di eventi. Anche se questo è più sicuro rispetto a condizioni di corsa e fornisce una maggiore consistenza, è considerevolmente meno intuitivo e più difficile da codificare di multitasking preemptive.

L'altro è una soluzione più tradizionale, più vicino allo stile di programmazione filettato, il programmatore solo dover passare manualmente contesto. Sebbene più incline alle condizioni di gara e alle situazioni di stallo, offre una facile soluzione drop-in.

La maggior parte del lavoro asincrono al momento viene eseguito su ciò che è noto come attività IO-bound, attività che bloccano l'attesa per l'input o l'output. Ciò è solitamente ottenuto mediante l'uso di funzioni di polling e timeout che possono essere richiamate e se restituiscono negativamente, il contesto può essere cambiato.

Nonostante il nome, questo potrebbe essere applicato a legati alla CPU compiti troppo, che possono essere delegati ad un altro lavoratore (filo, processo, ecc) e quindi non blockingly atteso per cedere. Idealmente, questi compiti sarebbero scritti in maniera asincrona-friendly, ma realisticamente ciò implicherebbe separare codice in piccoli pezzi abbastanza non bloccare, preferibilmente senza dispersione di contesto dopo ogni riga di codice. Ciò è particolarmente scomodo per le librerie sincrone esistenti.


Data la particolarità, ho scelto di utilizzare per il lavoro gevent asincrona e chiedevo come deve essere affrontato compiti legati alla CPU in un ambiente asincrono (tramite futures, sedano, ecc?).

Come utilizzare modelli di esecuzione asincrona (gevent in questo caso) con il framework web tradizionali come pallone? Quali sono alcune soluzioni comunemente concordate per questi problemi in python (future, code di attività)?

EDIT: Per essere più precisi - Come usare gevent con pallone e come trattare con compiti legati alla CPU in questo contesto?

EDIT2: Considerando quanto Python ha GIL che impedisce l'esecuzione ottimale del codice threaded, questo lascia solo l'opzione multiprocessing, nel mio caso almeno.Ciò significa utilizzare concurrent.futures o altri servizi esterni che si occupano dell'elaborazione (in grado di aprire le porte anche per qualcosa di linguistico agnostico). Quali sarebbero, in questo caso, alcune soluzioni diffuse o usate frequentemente con gevent (il sedano)? - best practice

+0

È possibile adottare questo modello in quasi tutte le librerie: http://bottlepy.org/docs/dev/async.html#event-callbacks. Suggerirei 'evergreen', perché consente di combinare attività cooperative (greenlets) con attività a esecuzione prolungata integrando una versione modificata di' concurrent.futures'. – schlamar

risposta

6

Dovrebbe essere thread-safe per fare qualcosa di simile a quanto segue per le attività ad alta intensità di CPU separate in discussioni asincroni:

from threading import Thread 

def send_async_email(msg): 
    mail.send(msg) 

def send_email(subject, sender, recipients, text_body, html_body): 
    msg = Message(subject, sender = sender, recipients = recipients) 
    msg.body = text_body 
    msg.html = html_body 
    thr = Thread(target = send_async_email, args = [msg]) 
    thr.start() 

SE avete bisogno di qualcosa di più complicato allora forse Flask-sedano o Multiprocessing libreria con "Pool, "potrebbe esserti utile.

Non ho molta familiarità con gevent anche se non riesco a immaginare quale più complessità potresti aver bisogno o perché.

Voglio dire, se stai tentando di avere l'efficienza di un importante sito web mondiale, allora ti consiglio di creare applicazioni C++ per fare il tuo lavoro a uso intensivo della CPU, e poi usare Flask-sedan o Pool per eseguire quel processo. (questo è ciò che YouTube fa mescolando C++ & Python)

+0

Qualche fonte per come lo fa Youtube (blogpost o qualcosa del genere)? – nikitautiu

+0

Ho finito per usare il sedano, ma come ho detto, in attesa di un risultato finisce per bloccare il webserver. La soluzione era quella di server l'app WSGI con il server gevent o gunicorn con gevent worker. Per il risultato asincrono, io scrivo semplicemente 'ready()' e se non è completo mi arrendo con un 'gevent.sleep()' canonico. – nikitautiu

+0

Ho paura di non avere un collegamento, ma il blog di Google potrebbe essere un posto dove cercarlo. – Dexter

1

Che ne dici di utilizzare semplicemente ThreadPool e Queue? È quindi possibile elaborare le tue cose in un thread separato in modo sincrono e non dovrai preoccuparti del blocco. Beh, Python non è adatto per compiti legati alla CPU in primo luogo, quindi dovresti anche pensare a generare sottoprocessi.

+0

Questa è una soluzione valida, e ce ne sono un altro che potrei pensare. Il punto è che mi stavo chiedendo come integrare gevent in una fiaschetta e in che modo le persone che usano gevent si occupano di situazioni in cui è impossibile che una task sincrona "verde" diventi borderline. – nikitautiu