Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

decorateur async await

0 votes

J'ai fait le code ci-dessous et j'ai voulu essayer de créer un décorateur pour gérer le subscribe.

Plutôt que de faire :

def on_leave():
    print("leave 1")
    self.leave()
await self.subscribe(on_leave, ROOT_FUNCTION % u'leave')

j'essaye de faire :

@self.subscribe2(ROOT_FUNCTION % u'leave')
def on_leave():
    print("leave 1")
    self.leave()

Mon code avec un exemple simple fonctionne, mais je ne sais pas pourquoi, le fait de ne pas avoir le await dans mon décorateur me fait dire que ça ne fait pas exactement la même chose.

Mon instinct me dit de virer mon code mais je préfère avoir votre avis avant de continuer.

from os import environ
import asyncio
from autobahn.asyncio.wamp import ApplicationSession, ApplicationRunner

ROOT_FUNCTION = u"fr.test.%s"


class CoworkerConnection(ApplicationSession):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.stop = False

    ####### le decorateur en question #########
    def subscribe2(self, name):
        print("in subscribe", self, name)

        def subscribe_decorator(func):
            print("hello")
            def wrapped(*func_args, **func_kwargs):
                return func(*func_args, **func_kwargs)

            self.subscribe(wrapped, name)        
            return wrapped

        return subscribe_decorator


    async def onJoin(self, details):

        ######l'appel du decorateur en question #######
        @self.subscribe2(ROOT_FUNCTION % u'leave2')
        async def on_test():
            print("leave 2")
            self.leave()

        def on_leave():
            print("leave 1")
            self.leave()

        await self.subscribe(on_leave, ROOT_FUNCTION % u'leave')

    def onDisconnect(self):
        asyncio.get_event_loop().stop()

if __name__ == '__main__':
    runner = ApplicationRunner(
        environ.get("AUTOBAHN_DEMO_ROUTER", u"ws://127.0.0.1:8080/ws"),
        u"crossbardemo",
    )
    runner.run(CoworkerConnection)
demandé 17-Aou-2016 par Johjo (220 points)

1 Réponse

0 votes
 
Meilleure réponse

Tu as raison ça ne fait pas la même chose car self.subscribe n'est du coup jamais programmé pour être exécuté pour l'event loop. Il est possible de le faire sans utiliser await heureusement, en utilisant la méthode ensure_future de ta loop.

Par exemple pour toi, quelque chose comme ça:

loop = asyncio.get_event_loop()
loop.ensure_future(self.subscribe(wrapped, name))
répondu 30-Aou-2016 par Sam (4,974 points)
sélectionné 1-Sep-2016 par Johjo

Après réecriture, j'ai extrait la méthode de la classe (je trouve plus sexy d'ecrire

@subscribe(self, u'fr.example.leave')

que

@self.subscribe(u'fr.example.leave')

mais ça n'engage que moi.

Le code du subscribe complet :

import asyncio

def subscribe(app_session, name):
    def subscribe_decorator(func):
        def wrapped(*func_args, **func_kwargs):
            return func(*func_args, **func_kwargs)

        asyncio.ensure_future(app_session.subscribe(wrapped, name))

        return wrapped
    return subscribe_decorator
...