Muestra las diferencias entre dos versiones de la página.
| Próxima revisión | Revisión previa | ||
|
fw:gevent [2013/07/04 16:38] alfred creado |
fw:gevent [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 59: | Línea 59: | ||
| Podemos hacer un cast a ''bool'' de una variable greenlet, esta será true si el greenlet está activo. | Podemos hacer un cast a ''bool'' de una variable greenlet, esta será true si el greenlet está activo. | ||
| + | |||
| + | ===== gevent ===== | ||
| + | * Para instalarlo has de tener instalado en el operativo la librería ''libevent-dev'' | ||
| + | * [[http://www.gevent.org/contents.html|Documentación]] | ||
| + | |||
| + | Es una librería basada en concurrencia por greenlets para desarrollar aplicaciones asíncronas, puede ser aprovechado es las funciones de network. \\ | ||
| + | El siguiente código: | ||
| + | <code python> | ||
| + | import gevent | ||
| + | def foo(): | ||
| + | print('Running in foo') | ||
| + | gevent.sleep(0) | ||
| + | print('Explicit context switch to foo again') | ||
| + | def bar(): | ||
| + | print('Explicit context to bar') | ||
| + | gevent.sleep(0) | ||
| + | print('Implicit context switch back to bar') | ||
| + | gevent.joinall([ | ||
| + | gevent.spawn(foo), | ||
| + | gevent.spawn(bar), | ||
| + | ]) | ||
| + | </code> | ||
| + | ... Se ejecuta de la siguiente forma: \\ | ||
| + | {{:fw:others:flow.gif?direct&200|}} | ||
| + | ==== Méotodos ==== | ||
| + | * ''gevent.spawn()'' | ||
| + | * ''gevent.joinall([gevents])'', detiene la ejecución del programa hasta que los greenlets no han acabado. | ||
| + | |||
| + | ==== Monkey patching ==== | ||
| + | Es una técnica que consiste en substituir llamadas a elementos del sistema que son bloqueantes por otras que no lo son y, de esa forma, adaptar código antiguo al nuevo. \\ | ||
| + | Por ejemplo existe una substitución a ''sleep''. La de la librería básica bloquea el event loop mientras que ''gevent.spleep'' no . \\ | ||
| + | Módulos que han sido substituidos: //socket//, //ssl//, //os//, //time//, //select//, //thread // y //threading//. | ||
| + | |||
| + | |||
| + | |||
| + | ===== Ejemplos ===== | ||
| + | === Métodos síncronos y asíncronos === | ||
| + | |||
| + | <code python> | ||
| + | import gevent | ||
| + | import random | ||
| + | |||
| + | def task(pid): | ||
| + | """ | ||
| + | Some non-deterministic task | ||
| + | """ | ||
| + | gevent.sleep(random.randint(0,2)*0.001) | ||
| + | print('Task', pid, 'done') | ||
| + | |||
| + | def synchronous(): | ||
| + | for i in range(1,10): | ||
| + | task(i) | ||
| + | |||
| + | def asynchronous(): | ||
| + | threads = [gevent.spawn(task, i) for i in xrange(10)] | ||
| + | gevent.joinall(threads) | ||
| + | |||
| + | print('Synchronous:') | ||
| + | synchronous() | ||
| + | |||
| + | print('Asynchronous:') | ||
| + | asynchronous() | ||
| + | </code> | ||
| + | <code> | ||
| + | Synchronous: | ||
| + | Task 1 done | ||
| + | Task 2 done | ||
| + | Task 3 done | ||
| + | Task 4 done | ||
| + | Task 5 done | ||
| + | Task 6 done | ||
| + | Task 7 done | ||
| + | Task 8 done | ||
| + | Task 9 done | ||
| + | Asynchronous: | ||
| + | Task 1 done | ||
| + | Task 2 done | ||
| + | Task 7 done | ||
| + | Task 6 done | ||
| + | Task 5 done | ||
| + | Task 0 done | ||
| + | Task 3 done | ||
| + | Task 8 done | ||
| + | Task 9 done | ||
| + | Task 4 done | ||
| + | </code> | ||
| + | |||
| + | === Acceso a red asíncronamente === | ||
| + | <code python> | ||
| + | import gevent.monkey | ||
| + | gevent.monkey.patch_socket() | ||
| + | |||
| + | import gevent | ||
| + | import urllib2 | ||
| + | import simplejson as json | ||
| + | |||
| + | def fetch(pid): | ||
| + | response = urllib2.urlopen('http://json-time.appspot.com/time.json') | ||
| + | result = response.read() | ||
| + | json_result = json.loads(result) | ||
| + | datetime = json_result['datetime'] | ||
| + | |||
| + | print 'Process ', pid, datetime | ||
| + | return json_result['datetime'] | ||
| + | |||
| + | def synchronous(): | ||
| + | for i in range(1,10): | ||
| + | fetch(i) | ||
| + | |||
| + | def asynchronous(): | ||
| + | threads = [] | ||
| + | for i in range(1,10): | ||
| + | threads.append(gevent.spawn(fetch, i)) | ||
| + | gevent.joinall(threads) | ||
| + | |||
| + | print 'Synchronous:' | ||
| + | synchronous() | ||
| + | |||
| + | print 'Asynchronous:' | ||
| + | asynchronous() | ||
| + | </code> | ||
| + | ===== Notas ===== | ||
| + | ==== ZeroMQ ==== | ||
| + | Para hacer el paquete ''pyzmq'' compatible con los greenlets instalaremos el paquete ''gevent-zeromq''. A partir de entonces instanciaremos zeromq de la siguiente forma: | ||
| + | <code python> | ||
| + | from gevent_zeromq import zmq | ||
| + | </code> | ||