sql >> Base de Datos >  >> RDS >> Mysql

¿Por qué el administrador de contexto MySQLdb Connection no cierra el cursor?

Para responder a su pregunta directamente:no veo ningún daño en cerrar al final de un with bloquear. No puedo decir por qué no se hace en este caso. Pero, como hay una escasez de actividad en esta pregunta, hice una búsqueda en el historial del código y arrojaré algunas ideas (suposiciones ) sobre por qué close() puede no ser llamado:

  1. Existe una pequeña posibilidad de que las llamadas a nextset() puede arrojar una excepción; posiblemente esto se haya observado y se haya visto como indeseable. Esta puede ser la razón por la cual la versión más nueva de cursors.py contiene esta estructura en close() :

    def close(self):
        """Close the cursor. No further queries will be possible."""
        if not self.connection:
            return
    
        self._flush()
        try:
            while self.nextset():
                pass
        except:
            pass
        self.connection = None
    
  2. Existe la posibilidad (algo remota) de que podría tomar algún tiempo revisar todos los resultados restantes sin hacer nada. Por lo tanto close() no se puede llamar para evitar hacer algunas iteraciones innecesarias. Si cree que vale la pena guardar esos ciclos de reloj es subjetivo, supongo, pero podría argumentar en la línea de "si no es necesario, no lo haga".

  3. Navegando por las confirmaciones de sourceforge, la funcionalidad fue agregada al tronco por esta confirmación en 2007 y parece que esta sección de connections.py no ha cambiado desde entonces. Esa es una fusión basada en esta confirmación , que tiene el mensaje

    Y el código que cita nunca ha cambiado desde entonces.

    Esto me lleva a mi pensamiento final:probablemente sea solo un primer intento / prototipo que funcionó y, por lo tanto, nunca se modificó.

Versión más moderna

Se vincula a la fuente de una versión heredada del conector. Observo que hay una bifurcación más activa de la misma biblioteca aquí , al que enlazo en mis comentarios sobre "versión más nueva" en el punto 1.

Tenga en cuenta que la versión más reciente de este módulo ha implementado __enter__() y __exit__() dentro del cursor sí mismo:ver aquí . __exit__() aquí hace llamar a self.close() y quizás esto proporcione una forma más estándar de usar la sintaxis with, por ejemplo,

with conn.cursor() as c:
    #Do your thing with the cursor

Notas finales

N.B. Supongo que debería agregar, según tengo entendido, la recolección de basura (tampoco soy un experto) una vez que no hay referencias a conn , se desasignará. En este punto, no habrá referencias al objeto del cursor y también se desasignará.

Sin embargo llamando a cursor.close() no significa que será basura recolectada. Simplemente graba los resultados y establece la conexión en None . Esto significa que no se puede reutilizar, pero no se recolectará como basura de inmediato. Puede convencerse de eso llamando manualmente a cursor.close() después de tu with bloquear y luego, digamos, imprimir algún atributo de cursor

N.B. 2 Creo que este es un uso algo inusual de with sintaxis como conn el objeto persiste porque ya está en el ámbito externo, a diferencia de, digamos, el with open('filename') as f: donde no hay objetos dando vueltas con referencias después del final de with bloquear.