2
votes

Que signifie «Impossible d'écrire sur le transport de fermeture»?

J'obtiens l'exception "Impossible d'écrire dans le transport de fermeture" levée de aiohttp.http_writer.StreamWriter # _write , mais seulement dans une fraction de cas.

Le extrait de code pertinent.

    session: aiohttp.ClientSession
    async with session.get(url, timeout=60) as response:
        txt = await response.text()
        response.close()
        return txt

Que se passe-t-il? Je ne pense pas que la taille du serveur ferme le socket.


4 commentaires

Comment est-ce possible? Dans ce code, nous attendons response.text (). Donc, si nous arrivons à response.close (), la réponse HTTP complète est terminée, non?


Vous pouvez reproduire ceci: ajoutez asyncio.sleep (10) à votre gestionnaire, appelez-le et arrêtez d'attendre (interrompre la connexion côté client) avant qu'il ne vous réponde. Vous verrez la même erreur dans les journaux du serveur


Je pense que lorsque vous fermez le serveur de connexion, il répond toujours smth. Pourquoi fermez-vous la connexion (response.close ()) manuellement? La connexion AFAIK se fermera automatiquement lorsque __aexit __ () de ClientSessionContextManager sera appelé.


Petite remarque: _SessionRequestContextManager et non ClientSessionContextManager


3 Réponses :


1
votes

Cela signifie que votre connexion est déjà fermée. Cela se produit lorsque le client rompt la connexion, mais le serveur essaie toujours de lui répondre.

Supprimez response.close () de votre code.


7 commentaires

Comment est-ce possible que la réponse HTTP continue, étant donné que response.text () a consommé toute la réponse?


@JoshuaFox Cela se produit parce que vous fermez la connexion manuellement ( response.close () ). Ne fais pas ça. Il sera fermé automatiquement lorsque vous sortirez de _SessionRequestContextManager


OK, ça a du sens


L'erreur est simplement que j'utilise response.close (). Si j'omets response.close (), le gestionnaire de contexte de session ferme la réponse de lui-même.


Je n'utilise pas de réponse close. Mais j'obtiens cette erreur lorsque le client se déconnecte parfois. Comment puis-je gérer cela? Essayez la capture sur l'émission Websocket ne fonctionne pas.


@TheFool AFAIK vous ne pouvez pas attraper ça.


@TheFool ou essayez d'encapsuler votre gestionnaire de contexte cs.request avec try ... catch



2
votes

Réponse: Nous devons créer une nouvelle session à chaque demande. Il n'est pas non plus nécessaire de fermer explicitement la response () , car le gestionnaire de contexte gère cela.

async with aiohttp.ClientSession().get(url, timeout=60) as response:
    txt = await response.text()
    return txt


1 commentaires

Une session dédiée pour chaque requête est ce qui m'a aidé à corriger l'exception Impossible d'écrire dans le transport de fermeture , bien que la documentation de aiohttp indique le contraire: Créez d'abord la session, utilisez l'instance permettant d'exécuter des requêtes HTTP et de lancer des connexions WebSocket. ( docs.aiohttp.org/en/v3.0.1/client_advanced.html#client-sess‌ ion ). J'utilise aiohttp 3.6.2 (2019-10-09) et Python 3.6.9 sur Ubuntu 18.04.4 LTS.



0
votes

Cela se produit si un client se déconnecte prématurément avant de lire tout ou partie de la réponse. Vous pouvez rencontrer ce cas fréquemment si vous traitez avec des clients mobiles (qui peuvent basculer entre le WiFi et les réseaux mobiles) ou si vous avez des vues qui prennent un certain temps, mais que les clients ont un délai d'expiration plus court. Puisque vous ne pouvez pas contrôler la manière dont les clients parlent à votre service, il est probablement prudent de l'ignorer.

aiohttp 3.6.0 introduit le code pour slience cette exception


0 commentaires