sql >> Database >  >> RDS >> Mysql

Waarom sluit de MySQLdb Connection-contextmanager de cursor niet?

Om je vraag direct te beantwoorden:ik zie geen enkel kwaad in het afsluiten aan het einde van een with blok. Ik kan niet zeggen waarom het in dit geval niet wordt gedaan. Maar aangezien er een gebrek aan activiteit is met betrekking tot deze vraag, heb ik de codegeschiedenis doorzocht en zal ik een paar gedachten opwerpen (gissingen ) over waarom de close() mag niet gebeld worden:

  1. Er is een kleine kans dat aanroepen naar nextset() kan een uitzondering veroorzaken - mogelijk was dit waargenomen en als ongewenst beschouwd. Dit is misschien de reden waarom de nieuwere versie van cursors.py bevat deze structuur 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. Er is het (enigszins afgelegen) potentieel dat het enige tijd kan duren om alle resterende resultaten te doorlopen terwijl u niets doet. Daarom close() mag niet worden aangeroepen om te voorkomen dat u onnodige iteraties uitvoert. Of je denkt dat het de moeite waard is om die klokcycli te bewaren, is subjectief, denk ik, maar je zou kunnen redeneren in de trant van "als het niet nodig is, doe het dan niet".

  3. Door de sourceforge-commits te bladeren, is de functionaliteit aan de trunk toegevoegd door deze commit in 2007 en het lijkt erop dat dit gedeelte van connections.py is sindsdien niet veranderd. Dat is een merge gebaseerd op deze commit , met de boodschap

    En de code die je citeert is sindsdien nooit meer veranderd.

    Dit roept mijn laatste gedachte op - het is waarschijnlijk slechts een eerste poging / prototype dat net werkte en daarom nooit is veranderd.

Moderne versie

U linkt naar de bron voor een oudere versie van de connector. Ik merk op dat er een actievere fork is van dezelfde bibliotheek hier , waarnaar ik link in mijn opmerkingen over "nieuwere versie" in punt 1.

Merk op dat de recentere versie van deze module __enter__() . heeft geïmplementeerd en __exit__() binnen cursor zelf:zie hier . __exit__() hier doet bel self.close() en misschien biedt dit een meer standaard manier om de syntaxis te gebruiken, bijvoorbeeld

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

Eindnoten

NB Ik denk dat ik moet toevoegen, voor zover ik het verzamelen van afval begrijp (ook geen expert) zodra er geen verwijzingen zijn naar conn , zal de toewijzing worden opgeheven. Op dit punt zijn er geen verwijzingen naar het cursorobject en wordt de toewijzing ook ongedaan gemaakt.

Echter aanroepen van cursor.close() betekent niet dat het afval wordt opgehaald. Het brandt gewoon de resultaten door en zet de verbinding op None . Dit betekent dat het niet opnieuw kan worden gebruikt, maar het zal niet meteen worden ingezameld. U kunt uzelf daarvan overtuigen door handmatig cursor.close() . aan te roepen na je with blokkeren en dan, laten we zeggen, een attribuut van cursor afdrukken

NB 2 Ik denk dat dit een ietwat ongebruikelijk gebruik is van de with syntaxis als de conn object blijft bestaan ​​omdat het zich al in de buitenste scope bevindt - in tegenstelling tot bijvoorbeeld de meer gebruikelijke with open('filename') as f: waar er geen objecten rondhangen met verwijzingen na het einde van de with blok.




  1. Selecteer rijen met maximale kolomwaarde groep op een andere kolom

  2. De beste manier om waarde uit het veld SET te verwijderen?

  3. Ontsnappen aan MySQL-wildcards

  4. PostgreSQL Reverse LIKE