Por que o gerenciador de contexto do MySQLdb Connection não fecha o cursor?

MySQLdbConnections ter um gerenciador de contexto rudimentar que cria um cursor ementrar, reverte ou confirma emSaída, e implicitamente não suprime exceções. DeFonte de conexão:

def __enter__(self):
    if self.get_autocommit():
        self.query("BEGIN")
    return self.cursor()

def __exit__(self, exc, value, tb):
    if exc:
        self.rollback()
    else:
        self.commit()

Então, alguém sabeporque o cursor não está fechado na saída?

No começo, eu assumi que era porque fechar o cursor não fazia nada e que os cursores só tinham um método próximo em deferência aoAPI de banco de dados Python (veja os comentários paraesta resposta) No entanto, o fato é que o fechamento do cursor queima nos demais conjuntos de resultados, se houver, e desativa o cursor. Defonte do cursor:

def close(self):
    """Close the cursor. No further queries will be possible."""
    if not self.connection: return
    while self.nextset(): pass
    self.connection = None

Seria tão fácil fechar o cursor na saída, por isso suponho que não tenha sido feito de propósito. Por outro lado, podemos ver que, quando um cursor é excluído, ele é fechado de qualquer maneira, então acho que o coletor de lixo acabará contornando. Eu não sei muito sobre coleta de lixo em Python.

def __del__(self):
    self.close()
    self.errorhandler = None
    self._result = None

Outro palpite é que pode haver uma situação em que você deseja reutilizar o cursor após owith quadra. Mas não consigo pensar em nenhum motivo para você precisar fazer isso. Você não pode sempre terminar de usar o cursor dentro de seu contexto e apenas usar um contexto separado para a próxima transação?

Para ser muito claro, este exemplo obviamente não faz sentido:

with conn as cursor:
    cursor.execute(select_stmt)

rows = cursor.fetchall()

Deveria ser:

with conn as cursor:
    cursor.execute(select_stmt)
    rows = cursor.fetchall()

Este exemplo também não faz sentido:

# first transaction
with conn as cursor:
    cursor.execute(update_stmt_1)

# second transaction, reusing cursor
try:
    cursor.execute(update_stmt_2)
except:
    conn.rollback()
else:
    conn.commit()

Deve ser apenas:

# first transaction
with conn as cursor:
    cursor.execute(update_stmt_1)

# second transaction, new cursor
with conn as cursor:
    cursor.execute(update_stmt_2)

Novamente, qual seria o problema em fechar o cursor na saída e quais são os benefícios de não fechá-lo?

questionAnswers(1)

yourAnswerToTheQuestion