sql >> Databáze >  >> RDS >> Mysql

Proč správce kontextu připojení MySQLdb nezavře kurzor?

Abych odpověděl přímo na vaši otázku:nevidím žádnou újmu v uzavření na konci with blok. Nemohu říci, proč se to v tomto případě nedělá. Ale protože je v této otázce nedostatek aktivity, nechal jsem si prohledat historii kódu a hodím pár myšlenek (hádám ), proč close() může nesmí se jmenovat:

  1. Existuje malá šance, že se točí prostřednictvím volání nextset() může vyvolat výjimku - možná to bylo pozorováno a považováno za nežádoucí. To může být důvod, proč novější verze cursors.py obsahuje tuto strukturu v 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. Existuje (poněkud vzdálený) potenciál, že to může nějakou dobu trvat, než se protočí všechny zbývající výsledky bez nečinnosti. Proto close() nemusí být voláno, aby se zabránilo provádění některých zbytečných iterací. Zda si myslíte, že stojí za to ukládat tyto hodinové cykly, je subjektivní, předpokládám, ale můžete argumentovat ve smyslu "pokud to není nutné, nedělejte to".

  3. Při procházení commitů sourceforge byla funkce přidána do kmene pomocí /a> v roce 2007 a zdá se, že tato část connections.py se od té doby nezměnilo. Jedná se o sloučení založené na tomto potvrzení , který má zprávu

    A kód, který citujete, se od té doby nikdy nezměnil.

    To podnítí mou poslední myšlenku - pravděpodobně je to jen první pokus / prototyp, který prostě fungoval, a proto se nikdy nezměnil.

Modernější verze

Odkazujete na zdroj pro starší verzi konektoru. Podotýkám, že existuje aktivnější větev stejné knihovny zde , na který odkazuji ve svých komentářích o "novější verzi" v bodě 1.

Všimněte si, že novější verze tohoto modulu implementovala __enter__() a __exit__() v cursor sám:viz zde . __exit__() zde dělá volání self.close() a možná to poskytuje standardnější způsob použití syntaxe with, např.

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

Konec poznámek

N.B. Myslím, že bych měl přidat, pokud rozumím shromažďování odpadu (ani nejsem odborník), jakmile nebudou žádné odkazy na conn , bude přiděleno. V tomto okamžiku nebudou žádné odkazy na objekt kurzoru a bude také uvolněn.

Nicméně volání cursor.close() neznamená, že se bude sbírat odpad. Jednoduše vypálí výsledky a nastaví připojení na None . To znamená, že jej nelze znovu použít, ale nebude okamžitě sesbírán. Můžete se o tom přesvědčit ručním voláním cursor.close() po vašem with blok a pak, řekněme, tisk nějakého atributu cursor

N.B. 2 Myslím, že toto je poněkud neobvyklé použití with syntaxe jako conn objekt přetrvává, protože je již ve vnějším rozsahu - na rozdíl například od běžnějšího with open('filename') as f: kde nejsou žádné objekty s odkazy za koncem with blokovat.




  1. Používat webovou službu s PL/SQL:UTL_DBWS nebo APEX_WEB_SERVICE?

  2. Jak mohu dále optimalizovat odvozený tabulkový dotaz, který funguje lépe než ekvivalent JOINed?

  3. MySql:pokud hodnota existuje UPDATE else INSERT

  4. CakePHP vnoření dvou vybraných dotazů