web-dev-qa-db-fra.com

dois-je appeler close () après urllib.urlopen ()?

Je suis nouveau sur Python et je lis le code de quelqu'un d'autre:

urllib.urlopen() doit-il être suivi de urllib.close()? Sinon, on perdrait les connexions, n'est-ce pas?

69
Nikita

La méthode close doit être appelée sur le résultat de urllib.urlopen, not sur le urllib module lui-même pendant que vous pensez (comme vous mentionnez urllib.close - qui n'existe pas).

La meilleure approche: au lieu de x = urllib.urlopen(u) etc, utilisez:

import contextlib

with contextlib.closing(urllib.urlopen(u)) as x:
   ...use x at will here...

L'instruction with et le gestionnaire de contexte closing assureront une fermeture correcte même en présence d'exceptions.

100
Alex Martelli

Comme le dit @Peter, les URL ouvertes hors de portée deviendront éligibles pour la collecte des ordures.

Cependant, notez également que urllib.py Définit:

 def __del__(self):
        self.close()

Cela signifie que lorsque le nombre de références pour cette instance atteint zéro , sa méthode __del__ sera appelée, et donc sa méthode close sera également appelée. Le moyen le plus "normal" pour que le nombre de références atteigne zéro est de simplement laisser l'instance hors de portée, mais rien ne vous empêche strictement d'un del x Explicite au début (mais il n'appelle pas directement __del__ Mais décrémente juste le nombre de références d'un).

C'est certainement un bon style pour fermer explicitement vos ressources - en particulier lorsque votre application court le risque d'utiliser trop de ces ressources - mais Python le fera nettoie automatiquement pour vous si vous ne faites rien de drôle comme le maintien de références (circulaires?) à des instances dont vous n'avez plus besoin.

12
Mark Rushakoff

Strictement parlant, c'est vrai. Mais en pratique, une fois (si) urllib hors de portée, la connexion sera fermée par le garbage collector automatique.

4
Peter

En gros , vous devez fermer explicitement votre connexion lorsque vous utilisez IronPython. La fermeture automatique en cas de sortie de portée dépend de la récupération de place. J'ai rencontré une situation où la récupération de place n'a pas fonctionné si longtemps que Windows a manqué de sockets. J'interrogeais un serveur Web à haute fréquence (c'est-à-dire aussi élevé que IronPython et la connexion le permettait, ~ 7 Hz). Je pouvais voir les "connexions établies" (c'est-à-dire les sockets utilisées) monter et monter sur PerfMon. La solution était d'appeler gc.collect() après chaque appel à urlopen.

0
Jann Poppinga