2017-09-13 3 views
3

Pour le code suivant à l'aide aiohttp:Quel est le problème avec ce code aiohttp asynchrone?

async def send(self, msg, url): 
    async with aiohttp.ClientSession() as session: 
     async with session.post(url, data=msg) as response: 
      self._msg = response.read() 

async def recv(self): 
    return await self._msg 

Il fonctionne ... La plupart du temps, mais parfois (souvent, en fait) donne lieu à diverses exceptions - réponses généralement tronquées, ou une connexion étant déjà fermée exception.

En revanche, ce qui suit fonctionne parfaitement:

async def send(self, msg, url): 
    async with aiohttp.ClientSession() as session: 
     async with session.post(url, data=msg) as response: 
      self._msg = await response.read() 

async def recv(self): 
    return self._msg 

Je voudrais savoir pourquoi, la deuxième version est techniquement incorrecte pour mes besoins et je dois corriger. (Il est incorrect car la fonction recv peut être appelée avant que la réponse ait été lue)

+0

"Il est incorrect car la fonction recv peut être appelée avant que la réponse ait été lue" - si c'est ca lled avant que la réponse a été lue, alors qu'est-ce que ça va 'attendre' dans la première version? 'self._msg' n'a pas encore été défini. – user2357112

+0

Exactement, le code que je viens de ne jamais appeler recv jusqu'à ce que l'envoi est terminé. Mais ah, c'est un très bon point, il s'avère que * les deux * versions sont fondamentalement fausses. Pouvez-vous suggérer une solution, tout en gardant le 'send' et le 'recv' séparés conceptuellement? – Arafangion

+0

(Pour clarifier: Bien que j'apprécierais le correctif, la vraie réponse que je veux sortir de ceci est de comprendre la différence entre ces deux exemples de code) – Arafangion

Répondre

2

with est un gestionnaire de contexte, il exécute du code avant et après toutes les instructions dans son bloc, la tenue de la comptabilité en général. C'est-à-dire que votre première fonction recv vous attend probablement sur un futur qui fait référence à une connexion déjà fermée, ou quelque chose du genre.

Disons que vous avez un code qui ressemble à ceci:

with open(...) as file: 
    file.read() 

C'est ce qu'il fait, à peu près:

file = open(...) 
file.read() 
file.close() 

Et cela est l'équivalent de ce que vous faites dans votre premier exemple:

file = open() 
file.close() 
... 
file.read() 
+0

Et cela invalide le futur? – Arafangion

+1

Je ne sais pas ce que vous entendez par "invalide le futur" exactement, mais, fondamentalement, toute cette question n'est pas un problème asyncique. C'est un problème de lecture à partir d'une socket fermée, ou quelque chose d'autre qui arrive en profondeur dans le 'response.read()'. –

+1

Mise à jour de la réponse. –