Ecco come scrivere correttamente quel codice:
db = create_engine('mysql://example@sqldat.com/test_database')
for i in range(1,2000):
conn = db.connect()
#some simple data operations
conn.close()
db.dispose()
Cioè, il Engine è una fabbrica per le connessioni e un pool di connessioni, non la connessione stessa. Quando dici conn.close() , la connessione viene restituita al pool di connessioni all'interno del motore , non effettivamente chiuso.
Se vuoi che la connessione sia effettivamente chiusa, cioè non raggruppata, disabilita il raggruppamento tramite NullPool :
from sqlalchemy.pool import NullPool
db = create_engine('mysql://example@sqldat.com/test_database', poolclass=NullPool)
Con il Engine sopra configurazione, ogni chiamata a conn.close() chiuderà la connessione DBAPI sottostante.
Se OTOH vuoi effettivamente connetterti a diversi database su ogni chiamata, ovvero il tuo "localhost/test_database" hardcoded è solo un esempio e in realtà hai molti database diversi, quindi l'approccio che utilizza dispose() è ok; chiuderà ogni connessione che non è stata estratta dal pool.
In tutti i casi precedenti, l'importante è che il Connection l'oggetto viene chiuso tramite close() . Se stai utilizzando qualsiasi tipo di esecuzione "senza connessione", è engine.execute() o statement.execute() , il ResultProxy l'oggetto restituito da quella chiamata di esecuzione deve essere letto completamente o altrimenti chiuso in modo esplicito tramite close() . Un Connection o ResultProxy che è ancora aperto vieterà il NullPool o dispose() si avvicina dalla chiusura di ogni ultima connessione.