Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Warum schließt der Kontextmanager MySQLdb Connection den Cursor nicht?

Um Ihre Frage direkt zu beantworten:Ich kann überhaupt keinen Schaden darin sehen, am Ende eines with zu schließen Block. Warum das in diesem Fall nicht gemacht wird, kann ich nicht sagen. Aber da es zu dieser Frage an Aktivität mangelt, habe ich den Codeverlauf durchsucht und werde ein paar Gedanken einwerfen (Vermutungen ) warum das close() kann nicht aufgerufen werden:

  1. Es besteht eine geringe Chance, dass Aufrufe von nextset() durchlaufen werden kann eine Ausnahme auslösen - möglicherweise wurde dies beobachtet und als unerwünscht angesehen. Dies könnte der Grund sein, warum die neuere Version von cursors.py enthält diese Struktur 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. Es besteht das (etwas entfernte) Potenzial, dass es einige Zeit dauern könnte, alle verbleibenden Ergebnisse durchzugehen, ohne etwas zu tun. Deshalb close() darf nicht aufgerufen werden, um einige unnötige Iterationen zu vermeiden. Ob Sie denken, dass es sich lohnt, diese Taktzyklen zu speichern, ist subjektiv, nehme ich an, aber Sie könnten nach dem Motto "wenn es nicht notwendig ist, tun Sie es nicht" argumentieren.

  3. Beim Durchsuchen der Sourceforge-Commits wurde die Funktionalität durch dieses Commit im Jahr 2007 und es scheint, dass dieser Abschnitt von connections.py hat sich seitdem nicht geändert. Das ist eine Zusammenführung basierend auf diesem Commit , die die Nachricht

    enthält

    Und der von Ihnen zitierte Code hat sich seitdem nie geändert.

    Dies veranlasst mich zu meinem letzten Gedanken - es ist wahrscheinlich nur ein erster Versuch / Prototyp, der gerade funktioniert hat und daher nie geändert wurde.

Modernere Version

Sie verlinken auf die Quelle für eine Legacy-Version des Connectors. Ich stelle fest, dass es hier einen aktiveren Fork derselben Bibliothek gibt , auf die ich in meinen Kommentaren zu "neuere Version" in Punkt 1 verlinke.

Beachten Sie, dass die neuere Version dieses Moduls __enter__() implementiert hat und __exit__() innerhalb von cursor selbst:siehe hier . __exit__() hier nicht ruft self.close() und vielleicht bietet dies eine standardisiertere Möglichkeit, die with-Syntax zu verwenden, z. B.

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

Endnotizen

NB. Ich denke, ich sollte hinzufügen, soweit ich die Garbage Collection verstehe (auch kein Experte), wenn es keine Verweise auf conn gibt , es wird freigegeben. An diesem Punkt gibt es keine Verweise auf das Cursor-Objekt und es wird auch freigegeben.

Allerdings Aufruf von cursor.close() bedeutet nicht, dass es Müll gesammelt wird. Es brennt einfach die Ergebnisse durch und setzt die Verbindung auf None . Dies bedeutet, dass es nicht wiederverwendet werden kann, aber es wird nicht sofort der Müllabfuhr zugeführt. Davon können Sie sich selbst überzeugen, indem Sie cursor.close() manuell aufrufen nach Ihrem with Block und dann, sagen wir, ein Attribut von cursor ausgeben

Hinweis:2 Ich denke, das ist eine etwas ungewöhnliche Verwendung von with Syntax als conn Das Objekt bleibt bestehen, weil es sich bereits im äußeren Gültigkeitsbereich befindet – im Gegensatz zu beispielsweise dem häufigeren with open('filename') as f: wo keine Objekte mit Verweisen nach dem Ende von with herumhängen blockieren.