2010-01-26 7 views
0

Je crée un programme python URL grabber. Pour mes besoins, je veux en temps, vraiment très très vite, donc je faisurllib2 expire mais ne ferme pas la connexion socket

urllib2.urlopen("http://.../", timeout=2)

Bien sûr, il fois correctement comme il se doit. Cependant, cela ne dérange pas de fermer la connexion au serveur, donc le serveur pense que le client est toujours connecté. Comment puis-je demander à urllib2 de fermer la connexion après l'expiration du délai?

L'exécution de gc.collect() ne fonctionne pas et je ne souhaite pas utiliser httplib si je ne peux pas m'en empêcher.

Le plus proche que je peux obtenir est: le premier essai expirera. Le serveur signale que la connexion s'est fermée juste lorsque le second essai expire. Ensuite, le serveur signale la connexion fermée juste comme le troisième essai expire. À l'infini.

Merci beaucoup.

Répondre

2

Je soupçonne que le socket est toujours ouvert dans les cadres de la pile. Lorsque Python déclenche une exception, il stocke les cadres de la pile afin que les débogueurs et les autres outils puissent afficher les valeurs de la pile et de l'introspection.

Pour des raisons historiques, et maintenant pour la rétrocompatibilité, les informations de la pile sont stockées (sur une base par thread) dans sys (voir sys.exc_info(), sys.exc_type et autres). C'est l'une des choses qui a été supprimée dans Python 3.0.

Ce que cela signifie pour vous, c'est que la pile est toujours en vie et référencée. La pile contient les données locales pour certaines fonctions qui ont le socket ouvert. C'est pourquoi le socket n'est pas encore fermé. Ce n'est que lorsque la trace de la pile est supprimée que tout sera gc'ed.

Pour vérifier si tel est le cas, insérez quelque chose comme

try: 
    1/0 
except ZeroDivisionError: 
    pass 

dans votre clause d'exception. C'est un moyen rapide de remplacer l'exception actuelle par autre chose.

+0

Hmm! Une pensée très intéressante. Merci, mais ça ne marche pas tout à fait; néanmoins, je n'y ai jamais pensé de cette façon. Je pense que pour mon projet, tout mon raisonnement est juste un peu trop hacky. Il vaudrait mieux que je ne m'en fie pas et que je termine simplement les connexions dupliquées sur le serveur. – Michael

0

Ceci est un tel bidouillage, mais le code suivant fonctionne. Si la requête est dans une autre fonction ET qu'elle ne déclenche pas d'exception, le socket est toujours fermé.

def _fetch(self, url): 
    try: 
     return urllib2.urlopen(urllib2.Request(url), timeout=5).read() 
    except urllib2.URLError, e: 
     if isinstance(e.reason, socket.timeout): 
      return None 
     else: 
      raise e 

def fetch(self, url): 
    x = None 
    while x is None: 
     x = self._fetch(url) 
     print "Timeout" 
    return x 

Est-ce que ANYONE a un meilleur moyen?

Questions connexes