Mysql
 sql >> Database >  >> RDS >> Mysql

Perché il gestore del contesto di MySQLdb Connection non chiude il cursore?

Per rispondere direttamente alla tua domanda:non vedo alcun danno nel chiudere alla fine di un with bloccare. Non posso dire perché non è fatto in questo caso. Ma, poiché c'è una carenza di attività su questa domanda, ho fatto una ricerca nella cronologia del codice e inserirò alcuni pensieri (ipotesi ) sul motivo per cui close() può non essere chiamato:

  1. C'è una piccola possibilità che girino le chiamate a nextset() può generare un'eccezione - forse questo è stato osservato e visto come indesiderabile. Questo potrebbe essere il motivo per cui la versione più recente di cursors.py contiene questa struttura in 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. C'è il potenziale (un po' remoto) che potrebbe volerci del tempo per girare tutti i risultati rimanenti senza fare nulla. Pertanto close() potrebbe non essere chiamato per evitare di eseguire alcune iterazioni non necessarie. Se pensi che valga la pena salvare quei cicli di clock è soggettivo, suppongo, ma potresti discutere sulla falsariga di "se non è necessario, non farlo".

  3. Sfogliando i commit di sourceforge, la funzionalità è stata aggiunta al trunk da questo commit nel 2007 e sembra che questa sezione di connections.py non è cambiato da allora. È un'unione basata su questo commit , che contiene il messaggio

    E il codice che citi non è mai cambiato da allora.

    Questo fa scattare il mio ultimo pensiero:probabilmente è solo un primo tentativo/prototipo che ha funzionato e quindi non è mai stato modificato.

Versione più moderna

Ti colleghi all'origine per una versione precedente del connettore. Prendo atto che esiste un fork più attivo della stessa libreria qui , a cui mi collego nei miei commenti sulla "versione più recente" al punto 1.

Nota che la versione più recente di questo modulo ha implementato __enter__() e __exit__() all'interno di cursor stesso:vedi qui . __exit__() qui fa chiama self.close() e forse questo fornisce un modo più standard per usare la sintassi with ad es.

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

Note finali

NB Immagino di dover aggiungere, per quanto ho capito, la raccolta dei rifiuti (nemmeno un esperto) una volta che non ci sono riferimenti a conn , sarà deallocato. A questo punto non ci saranno riferimenti all'oggetto cursore e verrà anche deallocato.

Comunque chiamando cursor.close() non significa che sarà la raccolta dei rifiuti. Brucia semplicemente i risultati e imposta la connessione su None . Ciò significa che non può essere riutilizzato, ma non verrà immediatamente raccolto. Puoi convincerti di ciò chiamando manualmente cursor.close() dopo il tuo with bloccare e poi, diciamo, stampare qualche attributo di cursor

NB 2 Penso che questo sia un uso alquanto insolito di with sintassi come conn l'oggetto persiste perché è già nell'ambito esterno - a differenza, diciamo, del più comune with open('filename') as f: dove non ci sono oggetti in giro con riferimenti dopo la fine di with blocco.