Python and MySQLdb - Using DROP TABLE IF EXISTS seems to throw exception - python

I got this code..
.....
try:
task_db.cursor.execute('DROP TABLE IF EXISTS `tasks`')
print "Affected: %d" % task_db.cursor.rowcount
except MySQLdb.Error, e:
print "Error ocurred: %s " % e.args[0]
print e
If the tasks table doesn't exist, then I get a warning like
create_database.py:11: Warning: Unknown table 'tasks'
But if the table does exist then I wont get that warning.
Odd?

Catching the MySQLdb.Warning didn't work for me, so I found another way to suppress warnings:
import warnings
warnings.filterwarnings("ignore", "Unknown table.*")
And you can edit the second parameter with whatever you want to suppress.

The most elegant way to avoid Mysql warnings :
from warnings import filterwarnings
import MySQLdb
filterwarnings('ignore', category = MySQLdb.Warning)

It's perfectly correct behaviour. If the table exists, then it's dropped. If it doesn't exist then you get Warning exception which is not the same as Error - you are free to ignore it and nothing bad should happen, but you have to catch it to allow your script to proceed.
EDIT:
To prevent Warning from bubbling up, just catch it as any other exception:
try:
[some code]
except MySQLdb.Warning:
[exception handling code]

Related

Catch any of the errors in psycopg2 without listing them explicitly

I have a try and except block where I would like to catch only the errors in the psycopg2.errors and not any other error.
The explicit way would be:
try:
# execute a query
cur = connection.cursor()
cur.execute(sql_query)
except psycopg2.errors.SyntaxError, psycopg2.errors.GroupingError as err:
# handle in case of error
The query will always be some SELECT statement. If the execution fails it should be handled. Any other exception not belonging to psycopg, e.g. like ZeroDivisionError, should not be caught from the except clause. However, I would like to avoid to list all errors after the except clause. In fact, if you list the psycopg errors, you get a quite extensive list:
from psycopg2 import errors
dir(errors)
I have searched quite extensively and am not sure if this question has been asked already.
You can you use the base class psycopg2.Error it catch all psycopg2 related errors
import psycopg2
try:
cur = connection.cursor()
cur.execute(sql_query)
except psycopg2.Error as err:
# handle in case of error
see official documentation
Meanwhile, I have implemented by catching a generic Exception and checking if the exception belongs to the list returned by dir(errors). The solution proposed by Yannick looks simpler, though.
The function that I use prints the error details and checks using the name of the exception err_type.__name__ whether it is in any of the psycopg errors:
from psycopg2 import errors
def is_psycopg2_exception(_err):
err_type, err_obj, traceback = sys.exc_info()
print ("\npsycopg2 ERROR:", _err, "on line number:", traceback.tb_lineno)
print ("psycopg2 traceback:", traceback, "-- type:", err_type)
return err_type.__name__ in dir(errors)
Then, I use this function in the try/except clause:
try:
# execute a query
cur = connection.cursor()
cur.execute(sql_query)
except Exception as err:
if is_psycopg2_exception(err):
# handle in case of psycopg error
else:
# other type of error
sys.exit(1) # quit
For my very specific case, where I need to check for other other exceptions as well, I can readapt Yannick solution as follows:
try:
# execute a query
cur = connection.cursor()
cur.execute(sql_query)
except psycopg2.OperationalError as err:
# handle some connection-related error
except psycopg2.Error as err:
# handle in case of other psycopg error
except Exception as err:
# any other error
sys.exit(1) # quit

Python/Django: how do I determine the class to specify in an "except" statement?

I am working with some Python/Django code that I inherited. In it there is a DB call surrounded by a try block, with an "except Exception ex" statement to catch all exceptions. I want to be more selective, and catch only the exception type that I anticipate. By examining the Exception object that is caught, I can tell that it's of type "DatabaseError".
The comments in my code below show the many things I have tried, based on Googling the question and searching here, along with the errors that Python gives me when I try them. Most frustrating is that I've found plenty of examples on the web of code the people say works, that looks just like what I'm trying. But the code samples I find generally don't include the "import" lines.
I suspect I need to import something more, but I can't figure out what.
import cx_Oracle
## import cx_Oracle.DatabaseError # creates an error saying "No name 'DatabaseError in module 'cx_Oracle'"
## from cx_Oracle import DatabaseError # creates an error saying "No name 'DatabaseError in module 'cx_Oracle'"
. . .
connection = connections['ims_db']
sqlUpdateQuery = "SELECT * FROM LOCKING WHERE IDENT={0} AND KEY_ID='SL_KEY' FOR UPDATE NOWAIT".format(self.serviceUid)
cursor = connection.cursor()
try:
cursor.execute(sqlUpdateQuery)
# this gets the error "Undefined variable 'Database'"
## except Database.DatabaseError as dbe3:
# this gets the error "Undefined variable 'Oracle'"
## except Oracle.DatabaseError as dbe2:
# this gets the error "Module 'cx_Oracle' has no 'DatabaseError' member"
## except cx_Oracle.DatabaseError as dbe:
# this gets the error "Undefined variable 'DatabaseError'"
## except DatabaseError as dbe:
# this gets the error "Catching an exception which doesn't inherit from BaseException: cx_Oracle"
## except cx_Oracle as dbe:
# this gets the error "Module cx_Oracle has no '_error' member"
## except cx_Oracle._Error as dbe:
except Exception as ex:
# This gets the error "Module cx_Oracle has no 'DatabaseError' member"
## if isinstance(ex, cx_Oracle.DatabaseError) :
# This gets the error "Undefined variable 'DatabaseError'"
## if isinstance(ex, DatabaseError) :
className = type(ex).__name__
# This logs "... class = DatabaseError ..."
log.error("Exception (class = {1}) while locking service {0}".format(self.serviceUid, className))
args = ex.args
arg0=args[0]
# arg0ClassName is "_Error"
arg0ClassName = type(arg0).__name__
code = arg0.code
# codeClassName is "int"
codeClassName = type(code).__name__
msg = "Exception, code = {0}".format(code)
log.debug(msg)
raise
The correct syntax is as follows:
try:
cur.execute("some_sql_statement")
except cx_Oracle.DatabaseError as e:
error, = e.args
print("CONTEXT:", error.context)
print("MESSAGE:", error.message)
You can see that syntax in a few of the samples (like TypeHandlers.py) that you can find here: https://github.com/oracle/python-cx_Oracle/tree/master/samples.
Try running the samples and working with them to see if you can resolve your issue. If not, please create an issue containing a complete runnable sample here: https://github.com/oracle/python-cx_Oracle/issues.

Handling PyMySql exceptions - Best Practices

My question regards exception best practices.
I'll present my question on a specific case with PyMySQL but it regards errors handling in general.
I am using PyMySQL and out of the many possible exceptions, there is one I want to deal with in a specific manner. "Duplicate" exception.
pymysql maps mysql errors to python errors according to the following table:
_map_error(ProgrammingError, ER.DB_CREATE_EXISTS, ER.SYNTAX_ERROR,
ER.PARSE_ERROR, ER.NO_SUCH_TABLE, ER.WRONG_DB_NAME,
ER.WRONG_TABLE_NAME, ER.FIELD_SPECIFIED_TWICE,
ER.INVALID_GROUP_FUNC_USE, ER.UNSUPPORTED_EXTENSION,
ER.TABLE_MUST_HAVE_COLUMNS, ER.CANT_DO_THIS_DURING_AN_TRANSACTION)
_map_error(DataError, ER.WARN_DATA_TRUNCATED, ER.WARN_NULL_TO_NOTNULL,
ER.WARN_DATA_OUT_OF_RANGE, ER.NO_DEFAULT, ER.PRIMARY_CANT_HAVE_NULL,
ER.DATA_TOO_LONG, ER.DATETIME_FUNCTION_OVERFLOW)
_map_error(IntegrityError, ER.DUP_ENTRY, ER.NO_REFERENCED_ROW,
ER.NO_REFERENCED_ROW_2, ER.ROW_IS_REFERENCED, ER.ROW_IS_REFERENCED_2,
ER.CANNOT_ADD_FOREIGN, ER.BAD_NULL_ERROR)
_map_error(NotSupportedError, ER.WARNING_NOT_COMPLETE_ROLLBACK,
ER.NOT_SUPPORTED_YET, ER.FEATURE_DISABLED, ER.UNKNOWN_STORAGE_ENGINE)
_map_error(OperationalError, ER.DBACCESS_DENIED_ERROR, ER.ACCESS_DENIED_ERROR,
ER.CON_COUNT_ERROR, ER.TABLEACCESS_DENIED_ERROR,
ER.COLUMNACCESS_DENIED_ERROR)
I want to specifically catch ER.DUP_ENTRY but I only know how to catch IntegrityError and that leads to redundant cases within my exception catch.
cur.execute(query, values)
except IntegrityError as e:
if e and e[0] == PYMYSQL_DUPLICATE_ERROR:
handel_duplicate_pymysql_exception(e, func_a)
else:
handel_unknown_pymysql_exception(e, func_b)
except Exception as e:
handel_unknown_pymysql_exception(e, func_b)
Is there a way to simply catch only ER.DUP_ENTRY some how?
looking for something like:
except IntegrityError.DUP_ENTRY as e:
handel_duplicate_pymysql_exception(e, func_a)
Thanks in advance for your guidance,
there is very generic way to use pymysql error handling. I am using this for sqlutil module. This way you can catch all your errors raised by pymysql without thinking about its type.
try:
connection.close()
print("connection closed successfully")
except pymysql.Error as e:
print("could not close connection error pymysql %d: %s" %(e.args[0], e.args[1]))
You cannot specify an expect clause based on an exception instance attribute obviously, and not even on an exception class attribute FWIW - it only works on exception type.
A solution to your problem is to have two nested try/except blocks, the inner one handling duplicate entries and re-raising other IntegrityErrors, the outer one being the generic case:
try:
try:
cur.execute(query, values)
except IntegrityError as e:
if e.args[0] == PYMYSQL_DUPLICATE_ERROR:
handle_duplicate_pymysql_exception(e, func_a)
else:
raise
except Exception as e:
handle_unknown_pymysql_exception(e, func_b)
Whether this is better than having a duplicate call to handle_unknown_pymysql_exception is up to you...

How to get the MySQL type of error with PyMySQL?

I'm doing a Python application with MySQL and PyMySQL and I'd like to be able to know the number of the MySQL error when I get one so that I can do something different depending on it.
Is there a way to do that with a try-except statement or another way?
Any exception in Python has an args member that shows you how it was constructed. For example:
>>> e = Exception(1, 2, 3, 4)
>>> e.args
(1, 2, 3, 4)
For pymysql, they're always constructed with (errno, errorvalue). So:
try:
do_stuff()
except MySQLError as e:
print('Got error {!r}, errno is {}'.format(e, e.args[0]))
I'm not sure this is guaranteed by the documentation, but you can see how it works pretty easily from the source.
pymysql maps mysql errors to python errors according to the following table:
_map_error(ProgrammingError, ER.DB_CREATE_EXISTS, ER.SYNTAX_ERROR,
ER.PARSE_ERROR, ER.NO_SUCH_TABLE, ER.WRONG_DB_NAME,
ER.WRONG_TABLE_NAME, ER.FIELD_SPECIFIED_TWICE,
ER.INVALID_GROUP_FUNC_USE, ER.UNSUPPORTED_EXTENSION,
ER.TABLE_MUST_HAVE_COLUMNS, ER.CANT_DO_THIS_DURING_AN_TRANSACTION)
_map_error(DataError, ER.WARN_DATA_TRUNCATED, ER.WARN_NULL_TO_NOTNULL,
ER.WARN_DATA_OUT_OF_RANGE, ER.NO_DEFAULT, ER.PRIMARY_CANT_HAVE_NULL,
ER.DATA_TOO_LONG, ER.DATETIME_FUNCTION_OVERFLOW)
_map_error(IntegrityError, ER.DUP_ENTRY, ER.NO_REFERENCED_ROW,
ER.NO_REFERENCED_ROW_2, ER.ROW_IS_REFERENCED, ER.ROW_IS_REFERENCED_2,
ER.CANNOT_ADD_FOREIGN, ER.BAD_NULL_ERROR)
_map_error(NotSupportedError, ER.WARNING_NOT_COMPLETE_ROLLBACK,
ER.NOT_SUPPORTED_YET, ER.FEATURE_DISABLED, ER.UNKNOWN_STORAGE_ENGINE)
_map_error(OperationalError, ER.DBACCESS_DENIED_ERROR, ER.ACCESS_DENIED_ERROR,
ER.CON_COUNT_ERROR, ER.TABLEACCESS_DENIED_ERROR,
ER.COLUMNACCESS_DENIED_ERROR)
if you want to catch the errors then you will need to catch ProgrammingError, DataError, IntegrityError, NotSupportedError, and OperationalError, individually. You can see specifically which mysql error was caught by coercing the exception to a string using str.
try:
#interact with pymysql
except ProgrammingError as e:
print "Caught a Programming Error:",
print e
for name, ddl in TABLES.iteritems():
try:
print("Creating table {}: ".format(name))
db.execute(ddl)
except pymysql.InternalError as error:
code, message = error.args
print ">>>>>>>>>>>>>", code, message
That's a start but loads of other errors exist eg. OperationalError

What could be the reason for lxml.etree.relaxng to return DocumentInvalid without logging an error?

I have code as follows:
try:
schema = lxml.etree.RelaxNG(file=schema_file)
schema.assertValid(etree)
except lxml.etree.DocumentInvalid as exception:
print(schema.error_log)
print(exception.error_log)
raise exception
It consistently raises a DocumentInvalid error:
DocumentInvalid: Document does not comply with schema
yet prints no errors in either the schema error log or the global error log.
This only happens for some files, others validate correctly, or give a reason for failing to validate. (It's a very long schema, so I won't quote it here.)
I don't even know where to start looking. What could the cause possibly be?
That is how you can get an error message
try:
schema = lxml.etree.RelaxNG(file=schema_file)
schema.assertValid(etree)
except lxml.etree.DocumentInvalid as exception:
print(exception.error_log.filter_from_errors()[0])
raise exception

Categories