5 votos

Devoluciones de llamada asíncronas con la API de Python para GEE

Al utilizar la API de Python para GEE, ¿es posible solicitar valores de un servidor de forma asíncrona?

Por ejemplo, en la API JS se puede utilizar .evaluate() pero en Python parece que sólo hay .getInfo() que bloquea temporalmente la siguiente ejecución del script. ¿Significa esto que no es posible hacer callbacks asíncronos con la API de Python?

5voto

Chris Kloberdanz Puntos 1871

Sí, es posible utilizar una de las pocas bibliotecas disponibles con una funcionalidad similar.

Asyncio es lo primero que me viene a la mente https://docs.python.org/3/library/asyncio.html Básicamente obtienes la funcionalidad de async/await, es posible crear callbacks.

Aquí hay una comparación paso a paso de la extracción de datos de forma asíncrona utilizando asyncio y la misma funcionalidad en node js: https://medium.com/@interfacer/intro-to-async-concurrency-in-python-and-node-js-69315b1e3e36 Si estás familiarizado con Javascript debería ser más fácil de entender.

Si necesitas una solución más sofisticada, especialmente para ejecutar tareas relativamente pesadas en segundo plano, te recomiendo otro de los conocidos módulos de Python: Celery https://docs.celeryproject.org/ que permite ejecutar funciones en trabajadores aislados (separados de la app que desencadena el trabajo). La idea básica de Celery es que las funciones que quieres ejecutar de forma asíncrona, deben ser envueltas con Celery que está escuchando a un broker de mensajes (Rabbit MQ, Redis, SQS etc.), entonces invocando esa función desde la app principal usando métodos dedicados envía argumentos al broker de mensajes y son pasados al worker que ejecuta la función y notifica al broker de mensajes que el trabajo ha sido terminado. Puede sonar un poco complicado pero recomiendo leer los documentos y ver los ejemplos.

3voto

hibbelig Puntos 176

Esta sería mi solución simple utilizando el threading módulo. Creo que asyncio es demasiado para un caso de uso simple, pero podría implementarse en una situación compleja como una aplicación web.

import ee
import threading
ee.Initialize()

def retrieve(f):
    def wrap(obj, *args):
        f(obj.getInfo(), *args)
    return wrap

def evaluate(obj, callback, args):
    args.insert(0, obj)
    callback = retrieve(callback)
    thd = threading.Thread(target=callback, args=args)
    thd.start()

# EE object
eeobj = ee.List([1,2,3,4,5,6])

# use case 1: printing values
def callback1(obj, n):
    print([i*n for i in obj])

evaluate(eeobj, callback1, [5])

# use case 2: filling a container
container = []
def callback2(obj, cont):
    """ filling a container """
    for item in obj:
        cont.append(item)

evaluate(eeobj, callback2, [container])
# wait 2 sec and...
print(container)

Para probarlo (en Spyder por ejemplo) recomiendo ejecutarlo por partes. Si lo ejecutas todo a la vez no podrás ver el comportamiento correctamente.

ACTUALIZACIÓN

puede utilizarlo a través del geetools paquete

import ee
ee.Initialize()
import geetools

# EE object
eeobj = ee.List([1,2,3,4,5,6])

# use case 1: printing values
def callback1(obj, n):
    print([i*n for i in obj])

geetools.evaluate(eeobj, callback1, [5])

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X