title: Why doesn't the MySQLdb Connection context manager close the cursor?
body: <p>MySQLdb <code>Connections</code> have a rudimentary context manager that creates a cursor on <em>enter</em>, either rolls back or commits on <em>exit</em>, and implicitly doesn't suppress exceptions. From the <a href="https://github.com/farcepest/MySQLdb1/blob/master/MySQLdb/connections.py" rel="nofollow noreferrer">Connection source</a>:</p>
  
  <pre><code>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()
  </code></pre>
  
  <p><strong>So, does anyone know <em>why</em> the cursor isn't closed on exit?</strong></p>
  
  <hr>
  
  <p>At first, I assumed it was because closing the cursor didn't do anything and that cursors only had a close method in deference to the <a href="https://www.python.org/dev/peps/pep-0249/#cursor-methods" rel="nofollow noreferrer">Python DB API</a> (see the comments to <a href="https://stackoverflow.com/a/22618781/484488">this answer</a>). However, the fact is that closing the cursor burns through the remaining results sets, if any, and disables the cursor. From the <a href="https://github.com/farcepest/MySQLdb1/blob/master/MySQLdb/cursors.py" rel="nofollow noreferrer">cursor source</a>:</p>
  
  <pre><code>def close(self):
      """Close the cursor. No further queries will be possible."""
      if not self.connection: return
      while self.nextset(): pass
      self.connection = None
  </code></pre>
  
  <p>It would be so easy to close the cursor at exit, so I have to suppose that it hasn't been done on purpose. On the other hand, we can see that when a cursor is deleted, it is closed anyway, so I guess the garbage collector will eventually get around to it. I don't know much about garbage collection in Python.</p>
  
  <pre><code>def __del__(self):
      self.close()
      self.errorhandler = None
      self._result = None
  </code></pre>
  
  <hr>
  
  <p>Another guess is that there may be a situation where you want to re-use the cursor after the <code>with</code> block. But I can't think of any reason why you would need to do this. Can't you always finish using the cursor inside its context, and just use a separate context for the next transaction?</p>
  
  <p>To be very clear, this example obviously doesn't make sense:</p>
  
  <pre><code>with conn as cursor:
      cursor.execute(select_stmt)
  
  rows = cursor.fetchall()
  </code></pre>
  
  <p>It should be:</p>
  
  <pre><code>with conn as cursor:
      cursor.execute(select_stmt)
      rows = cursor.fetchall()
  </code></pre>
  
  <p>Nor does this example make sense:</p>
  
  <pre><code># 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()
  </code></pre>
  
  <p>It should just be:</p>
  
  <pre><code># first transaction
  with conn as cursor:
      cursor.execute(update_stmt_1)
  
  # second transaction, new cursor
  with conn as cursor:
      cursor.execute(update_stmt_2)
  </code></pre>
  
  <p><strong>Again, what would be the harm in closing the cursor on exit, and what benefits are there to not closing it?</strong> </p>