10
votes

Callbacks et générateurs asynchrones Python

J'essaie de convertir une bibliothèque synchrone pour utiliser un cadre interne de l'IO asynchrone. J'ai plusieurs méthodes qui ressemblent à ceci: xxx pré>

pour chacune des fonctions synchrones ( sync_call _ * code>), j'ai écrit une fonction Async correspondante qui prend un rappel. E.g. P>

def async_foo(callback):
  # Do the foo() stuff using async_call_*
  callback()


0 commentaires

3 Réponses :


2
votes

Il y a plusieurs tâches de multiplexage. Nous ne pouvons pas dire quel est le meilleur pour votre cas sans savoir ce que vous faites. Probablement la manière la plus la plus facile / universelle est d'utiliser des threads. Jetez un coup d'œil à Cette question pour quelques idées.


0 commentaires

10
votes

mise à jour : prenez ceci avec un grain de sel, car je suis hors de contact avec les développements modernes de Python ASYNC, y compris gevent et asyncio et N'avez pas vraiment une expérience sérieuse avec le code ASYNC.


Il y a 3 approches communes de la codage ASYNC sans fil en python:

  1. Callbacks - moche mais fonctionnel, tordu ce qui est bien.

  2. Générateurs - Nice mais exigent tous votre code pour suivre le style.

  3. Utilisez la mise en oeuvre Python avec de vrais groupes de tâches - Stackless (RIP) et Greenlet .

    Malheureusement, idéalement, tout le programme doit utiliser un style ou des choses compliquées. Si vous acceptez votre bibliothèque exposant une interface entièrement synchrone, vous allez probablement bien, mais si vous souhaitez que plusieurs appels à votre bibliothèque fonctionnent en parallèle, en particulier en parallèle avec autre code async, vous avez besoin de un événement commun "réacteur" qui peut fonctionner avec tout le code.

    Donc, si vous avez (ou si vous avez l'utilisateur d'avoir) d'autres codes ASYNC dans l'application, adopter le même modèle est probablement intelligent.

    Si vous ne voulez pas comprendre tout le gâchis, envisagez d'utiliser de mauvais vieux threads. Ils sont aussi laids, mais travaillent avec tout le reste.

    Si vous voulez comprendre comment les coroutines pourraient vous aider - et comment elles pourraient vous compliquer, David Beazley's " Un cours curieux sur les coroutines et la concurrence " est de bonnes choses.

    Greenlets pourrait être actuellement le moyen le plus propre si vous pouvez utiliser l'extension. Je n'ai aucune expérience avec eux, alors ne peut pas dire grand chose.


0 commentaires

2
votes

Vous devez créer une fonction foo code> aussi async. Qu'en est-il de cette approche?

def make_async(f):
    """Decorator to convert sync function to async
    using the above mentioned transformations"""
    def g(*a, **kw):
        async_call(f(*a, **kw))
    return g

def async_call(it, value=None):
    # This function is the core of async transformation.

    try: 
        # send the current value to the iterator and
        # expect function to call and args to pass to it
        x = it.send(value)
    except StopIteration:
        return

    func = x[0]
    args = list(x[1:])

    # define callback and append it to args
    # (assuming that callback is always the last argument)

    callback = lambda new_value: async_call(it, new_value)
    args.append(callback)

    func(*args)


0 commentaires