2009-10-05 17 views

Respuesta

94

El método close deben ser llamados en el resultado de urllib.urlopen, no en el módulo urllib como usted está pensando (como usted menciona urllib.close - que no existe).

El mejor enfoque: en lugar de x = urllib.urlopen(u) etc, utilice:

import contextlib 

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

La declaración with, y el gerente closing contexto, se asegurará un cierre adecuado, incluso en presencia de excepciones.

+8

¿qué tal hacer algo como 'data = urllib2.urlopen ('url'). Read()' –

+13

En Python 3, se agregó soporte directo para la instrucción with. con urllib.urlopen (u) como x: ... –

3

Estrictamente hablando, esto es cierto. Pero en la práctica, una vez (si) urllib sale del alcance, la conexión será cerrada por el recolector de basura automático.

+10

Esto es cierto para algunas implementaciones de Python, pero el lenguaje Python no garantiza que el cierre ocurra tan pronto como el objeto salga del alcance. cf. jython –

+1

@gnibbler El autor de esta respuesta no dice que va a suceder * tan pronto como * solo que sucederá. –

+2

@Piotr, pero tal vez el programa falle si tengo una url de apertura de bucle y el GC no los está recogiendo lo suficientemente rápido. Es una forma bastante descuidada de hacer cosas y no pertenece al código de producción. –

11

Como dice @Peter, las URL abiertas fuera del alcance serán elegibles para la recolección de basura.

Sin embargo, también observamos que urllib.py define:

def __del__(self): 
     self.close() 

Esto significa que cuando el recuento de referencia para esa instancia llega a cero, su método __del__ será llamado, y por lo tanto su método close será llamado como bien. La forma más "normal" para que el recuento de referencias llegue a cero es simplemente dejar que la instancia salga del alcance, pero no hay nada estrictamente que lo detenga de forma explícita del x anticipadamente (sin embargo, no llama directamente al __del__ sino que simplemente disminuye el recuento de referencias) por uno).

Ciertamente, es un buen estilo para cerrar de forma explícita sus recursos, especialmente cuando su aplicación corre el riesgo de utilizar demasiados de dichos recursos, pero Python se limpiará automáticamente si no hace nada gracioso como manteniendo (¿circular?) referencias a instancias que ya no necesita.

+2

Es posible, sin embargo, sobrepasar el recolector de basura - He tenido casos donde estoy creando archivos maneja más rápido de lo que los cierra [pero donde explícito 'gc.collect() 'call, or a' close() ', cosas limpias]. –

Cuestiones relacionadas