Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Dlaczego menedżer kontekstu MySQLdb Connection nie zamyka kursora?

Aby odpowiedzieć bezpośrednio na twoje pytanie:nie widzę żadnej szkody w zamykaniu na końcu with blok. Nie potrafię powiedzieć, dlaczego nie robi się tego w tym przypadku. Jednak ze względu na brak aktywności w tej kwestii, przeszukałem historię kodu i wrzucę kilka przemyśleń (domysłów ) o tym, dlaczego close() może nie nazywać się:

  1. Istnieje niewielka szansa, że ​​przejdziemy przez wywołania nextset() może zgłosić wyjątek — prawdopodobnie został on zaobserwowany i uznany za niepożądany. Może dlatego nowsza wersja cursors.py zawiera tę strukturę w 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. Istnieje (nieco odległy) potencjał, że może zająć trochę czasu, aby przejść przez wszystkie pozostałe wyniki, nie robiąc nic. Dlatego close() nie może zostać wywołany, aby uniknąć niepotrzebnych iteracji. Przypuszczam, że to, czy uważasz, że warto oszczędzać te cykle zegara, jest subiektywne, ale możesz argumentować w stylu „jeśli nie jest to konieczne, nie rób tego”.

  3. Przeglądając zatwierdzenia Sourceforge, funkcjonalność została dodana do bagażnika przez to zatwierdzenie w 2007 roku i wygląda na to, że ta sekcja connections.py nie zmienił się od tego czasu. To scalanie oparte na tym zatwierdzeniu , który zawiera komunikat

    A cytowany przez Ciebie kod nigdy się nie zmienił.

    To skłania do mojej ostatniej myśli - to prawdopodobnie tylko pierwsza próba / prototyp, który po prostu działał i dlatego nigdy się nie zmienił.

Bardziej nowoczesna wersja

Łączysz ze źródłem starszej wersji oprogramowania sprzęgającego. Zauważam, że istnieje bardziej aktywny widelec tej samej biblioteki tutaj , do którego odsyłam w komentarzach na temat „nowszej wersji” w punkcie 1.

Zauważ, że w nowszej wersji tego modułu zaimplementowano __enter__() i __exit__() wewnątrz cursor sam:zobacz tutaj . __exit__() tutaj robi wywołaj self.close() i być może zapewnia to bardziej standardowy sposób używania składni ze składnią, np.

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

Uwagi końcowe

Uwaga Myślę, że powinienem dodać, o ile rozumiem odśmiecanie (też nie ekspert), gdy nie ma odniesień do conn , zostanie cofnięty alokacja. W tym momencie nie będzie żadnych odniesień do obiektu kursora i zostanie on również cofnięty.

Jednak wywołanie cursor.close() nie oznacza, że ​​będą zbierane śmieci. Po prostu sprawdza wyniki i ustawia połączenie na None . Oznacza to, że nie można ich ponownie użyć, ale nie zostaną one natychmiast zebrane. Możesz się o tym przekonać, ręcznie wywołując cursor.close() po twoim with blokuje, a następnie, powiedzmy, wypisuje jakiś atrybut cursor

Uwaga 2 Myślę, że jest to nieco nietypowe użycie with składnia jako conn obiekt utrzymuje się, ponieważ znajduje się już w zewnętrznym zakresie - w przeciwieństwie, powiedzmy, bardziej powszechnego with open('filename') as f: gdzie nie ma żadnych obiektów wiszących z referencjami po zakończeniu with blokować.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. LEFT JOIN nie zwraca wszystkich rekordów z lewej strony tabeli

  2. AWS Lambda - buforowanie MySQL

  3. MySQL Workbench:Nie można połączyć się z serwerem MySQL w przypadku błędu 127.0.0.1' (10061)

  4. Hierarchia kategorii (PHP/MySQL)

  5. Napraw za pomocą gdzie; Korzystanie tymczasowe; Korzystanie z sortowania plików