| Bug #74742 | mysql-connector-python 2.0.2 inconvenient exception handling | ||
|---|---|---|---|
| Submitted: | 7 Nov 2014 20:24 | Modified: | 30 May 2022 9:56 | 
| Reporter: | Andrew Garner | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | Connector / Python | Severity: | S3 (Non-critical) | 
| Version: | 2.0.2 | OS: | Any | 
| Assigned to: | CPU Architecture: | Any | |
   [7 Nov 2014 20:44]
   Andrew Garner        
  Here is a traceback for a simple reproduction of this bug:
$ cat interrupt.py
import os
import mysql.connector
c = mysql.connector.connect(option_files=[os.path.expanduser('~/.my.cnf')])
while True:
    z = c.cursor()
$ python interrupt.py
^CTraceback (most recent call last):
  File "interrupt.py", line 6, in <module>
    z = c.cursor()
  File "/usr/lib/python2.6/site-packages/mysql/connector/connection.py", line 1383, in cursor
    raise errors.OperationalError("MySQL Connection not available.")
mysql.connector.errors.OperationalError: MySQL Connection not available.
Here I would rather except to see a KeyboardInterrupt.   And I do most times, of course, it all depends on where the code is when SIGINT is caught.
Tested on CentOS 6.6 with mysql-connector-python-2.0.2-1.el6.noarch from the mysql community yum repo.
 
   [10 Nov 2014 9:54]
   MySQL Verification Team        
  Hello Andrew Garner, Thank you for the report. Thanks, Umesh
   [10 Nov 2014 9:54]
   MySQL Verification Team        
  // on OL6
 
[root@cluster-repo setups]# python
Python 2.6.6 (r266:84292, Jan 22 2014, 01:49:05)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import os
>>> import mysql.connector
>>> c = mysql.connector.connect(option_files=[os.path.expanduser('~/.my.cnf')])
>>> while True:
...     z = c.cursor()
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/mysql/connector/connection.py", line 1383, in cursor
mysql.connector.errors.OperationalError: MySQL Connection not available.
[root@cluster-repo setups]# rpm -qa|grep mysql-connector
mysql-connector-python-commercial-2.0.2-1.el6.noarch
[root@cluster-repo setups]#
[root@cluster-repo setups]# python --version
Python 2.6.6
 
   [4 May 2022 14:38]
   Nuno Mariz        
  Posted by developer: The `cnx.is_connected()` does not raise any exception by design. For catching any exception in this context use `cnx.cmd_ping()`.
   [30 May 2022 9:56]
   Nuno Mariz        
  Posted by developer: With the changes performed in WL#15137 (Fix linting issues), is_connected() now catches only Connector/Python Error based exceptions. Thank you for the bug report.

Description: mysql-python-connector 2.0 is trapping all exceptions in various places due to a bare except catch all. This occurs in at least the mysql/connector/connection.py:is_connected(), ping() and cmd_change_user() methods. I ran into headaches here in the cursor() -> is_connected() path. The exception handling here can end up swallowing a KeyboardInterrupt exception and making pretty error handling difficult. How to repeat: Trigger a KeyboardInterrupt during an is_connected() check and see the exception swallowed. Suggested fix: I ran into this primarily in the cursor() -> is_connected() code path where I see the implementation is: def is_connected(self): """Reports whether the connection to MySQL Server is available This method checks whether the connection to MySQL is available. It is similar to ping(), but unlike the ping()-method, either True or False is returned and no exception is raised. Returns True or False. """ try: self.cmd_ping() except: return False # This method does not raise return True The suggested fix is to not use a bare except but restrict the exceptions to those commonly raised by cmd_ping() - or at the very least reraise KeyboardInterrupt/SystemExit as needed.