I am using Python/Bottle/SqlAlchemy/MySQL for a web service.
I am trying to catch an IntegrityError raised by calling a stored procedure but I am unable to do that.
Using this
cursor = connection.cursor()
cursor.callproc('my_stored_proc', [arguments])
yields the same result as
try:
cursor = connection.cursor()
cursor.callproc('my_stored_proc', [arguments])
except IntegrityError as e:
print("Error: {}".format(e))
return {"message": e.message}
I get an IntegrityError exception in both cases. Why is the exception not caught in the latter case?
The problem was I was catching the incorrect exception.
It turned out the error raised is actually of type pymysql.err.IntegrityError and not sqlalchemy.exc.IntegrityError as I assumed.
I found out the exception type by doing:
import sys
try:
cursor = connection.cursor()
cursor.callproc('my_stored_proc', [arguments])
except:
print "Unexpected error:", sys.exc_info()[0]
And I saw this printout:
Unexpected error: <class 'pymysql.err.IntegrityError'>
In my case, and also yours, you'd use the sqlalchemy object:
try:
cursor = connection.cursor()
cursor.callproc('my_stored_proc', [arguments])
except sqlalchemy.exc.IntegrityError as e:
print("Error: {}".format(e))
return {"message": e.message}
In my case and may be this helps you too, I was using MYSQL as database so to catch exceptions I need to import exceptions
from django.db.utils import IntegrityError
Then you can try and catch it like this
try:
#your code
except IntegrityError:
#your code when integrity error comes
With pymysql I use:
import pymysql
# some code
try:
#Your code
except pymysql.err.IntegrityError:
# Your exception code
except Exception as e:
# Raise all other exceptions.
raise e
Related
I have been wrestling with this issue and i can't figure it out nor do i expect to given my limited experience. It is part of my login_portal which is attached to a database on MySQL and everything works well except i have that recurring message when running.
I have placed pass, Exception and ValueException in the except blocks still with the same result...
Which given the semantics of the TypeError message just does not compute i feel i have satisfied the problem three-fold.
The error i keep getting at the bottom when running my scripts is below-
Exception ignored in: <function BaseMySQLSocket.del at 0x000001A7375131F0>
Traceback (most recent call last):
File "C:\Users\georg\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\mysql\connector\network.py", line 149, in del
File "C:\Users\georg\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\mysql\connector\network.py", line 137, in shutdown
TypeError: catching classes that do not inherit from BaseException is not allowed
I am sure "create_db_connection" is my problem function:
# Functions
def create_db_connection(host_name, user_name, pass_word, db_name):
connection = None
try:
connection = mysql.connector.connect(
host=host_name,
user=user_name,
passwd=pass_word,
database=db_name
)
print("MySQL Database connection successful")
except Error as err:
print(f"Error: '{err}'")
def read_query(connection, query):
cursor = connection.cursor()
result = None
try:
cursor.execute(query)
result = cursor.fetchall()
return result
except Error as err:
print(f"Error: '{err}'")
# My calls
connection = create_db_connection('localhost', 'root', 'GeoPlayingCode17##',
'login_details')
results = read_query(connection, q1)
You are trying to catch an exception that is not from the BaseException. Thats where exceptions are defined.
Try this
try:
Do_something()
except Exception as Ex:
print(Ex)
This must sort it out
I am trying to write function for updating database table columns (here column name will differ various point of time.) So while doing so, i am getting "operation error, Database locked". Could anyone suggest reason behind this.
For more clarification i am providing code as below:
def UpdateDB_ForFields(DB_name, DB_tableName, dev_name, devindex, colList, colValList):
try:
conn = None
cloudDBlockList[devindex].acquire()
pool_sema.acquire()
conn = sqlite3.connect("XYZ.db",timeout=20)
for i in range(len(colList)):
cursor = conn.execute("""UPDATE XYZ_settings SET {0} = ? WHERE {1} = ?;""".format(colList[i],"devName"),(colValList[i],dev_name))
conn.commit()
conn.close()
pool_sema.release()
cloudDBlockList[devindex].release()
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
message = template.format(type(ex).__name__, ex.args)
print(message)
logging.error(message)
if conn == None:
print("Error")
else:
conn.close()
pool_sema.release()
cloudDBlockList[devindex].release()
I am getting error while updating db as database locked. Please suggest the solution.
I am writing a function to that can add a new table to my database. The problem I am having is when the table already exist I get the error message:
pymysql.err.InternalError: (1050, "Table 'doesthiswork' already exists")
So I added an except to my code which works but it is excepting all Internal errors. How do I get my code to except the specific error which I am assuming is 1050 not Internal Errors in general?
import pymysql
def CreateTable(Host,User,Password,DataBase,TableName):
try:
conn = pymysql.connect(
host = Host,
user = User,
password= Password,
db = DataBase
)
a = conn.cursor()
tblName = TableName
sql = 'CREATE TABLE'+" "+ tblName + '(try varchar(128));'
a.execute(sql)
except pymysql.err.InternalError:
print (tblName + " " + 'already exist')
The above code works, but as stated earlier if a different type of internal error surfaced it would just except that as table already exist not the actual error itself.
Assign the exception to a variable and test the specific error codes, e.g.:
except pymysql.err.InternalError as e:
code, msg = e.args
if code == 1050:
print(tblName, 'already exists')
Though you can probably just print(msg).
You don't have to hardcode the code values, they are available in the pymysql.constants.ER module. And you can have a mapping between error codes and error messages, which can help to scale this approach to handling more errors without multiplying the if/else blocks:
from pymysql.constants import ER
error_codes = {
ER.TABLE_EXISTS_ERROR: "Table already exists",
ER.ACCESS_DENIED_ERROR: "Access denied"
}
try:
# ...
except pymysql.err.InternalError as e:
code, msg = e.args
print(error_codes.get(code, msg))
You can add an additional catch-all "except" like so:
try:
# your code here
except pymysql.err.InternalError:
print('already exists')
except:
print('catch-all exception!')
This question already has answers here:
unbound method f() must be called with fibo_ instance as first argument (got classobj instance instead)
(8 answers)
Closed 6 years ago.
I have reviewed the error on Stackoverflow, but none of the solutions I've seen resolve my problem. I'm attempting to create a class for cx_Oracle to put my database connectivity in a class, and call it during my database instances.
I've created similar classes in C#, but python is especially difficult for some reason. Any assistance appreciated.
I leveraged this code found here:
cx_Oracle and Exception Handling - Good practices?
import sys
import os
import cx_Oracle
class Oracle(object):
__db_server = os.getenv("ORACLE_SERVER")
__db_user = os.getenv("ORACLE_ACCT")
__db_password = os.getenv("ORACLE_PWD")
def connect(self):
""" Connect to the database. """
try:
self.db = cx_Oracle.connect(__db_user+'/'+__db_password+'#'+__db_server)
except cx_Oracle.DatabaseError as e:
error, = e.args
if error.code == 1017:
print('Please check your credentials.')
else:
print('Database connection error: %s'.format(e))
# Very important part!
raise
# If the database connection succeeded create the cursor
# we-re going to use.
self.cursor = db.Cursor()
def disconnect(self):
"""
Disconnect from the database. If this fails, for instance
if the connection instance doesn't exist we don't really care.
"""
try:
self.cursor.close()
self.db.close()
except cx_Oracle.DatabaseError:
pass
def execute(self, sql, bindvars=None, commit=False):
"""
Execute whatever SQL statements are passed to the method;
commit if specified. Do not specify fetchall() in here as
the SQL statement may not be a select.
bindvars is a dictionary of variables you pass to execute.
"""
try:
self.cursor.execute(sql, bindvars)
except cx_Oracle.DatabaseError as e:
error, = e.args
if error.code == 955:
print('Table already exists')
elif error.code == 1031:
print("Insufficient privileges")
print(error.code)
print(error.message)
print(error.context)
# Raise the exception.
raise
# Only commit if it-s necessary.
if commit:
self.db.commit()
def select(self, sql, commit=False):
bindvars=None
result = None
try:
self.cursor.execute(sql, bindvars)
result = self.cursor.fetchall()
except cx_Oracle.DatabaseError as e:
error, = e.args
print "Database Error: failed with error code:%d - %s" % (error.code, error.message)
raise
if commit:
self.db.commit()
return result
def commit(self):
try:
self.db.commit()
except cx_Oracle.DatabaseError as e:
error, = e.args
print "Database Commit failed with error code:%d - %s" % (error.code, error.message)
raise
def rollback(self):
try:
self.db.rollback()
except cx_Oracle.DatabaseError as e:
error, = e.args
print "Database Rollback failed with error code:%d - %s" %(error.code, error.message)
raise
And this is my calling routine
import sys
import os
#import cx_Oracle
from Oracle import Oracle
def main():
oracle = Oracle.connect()
query = """SELECT DISTINCT NAME FROM MyTable"""
data = oracle.select(query)
for row in data:
print row
oracle.disconnect()
### MAIN
if __name__ == '__main__':
main()
On a related note: I can't seem to get Python to find my Oracle.py class, unless it's in the same directory as the calling function.
Allan
You have to create an instance of your class to use it:
orcl = Oracle()
orcl.connect()
...
Assuming this piece of code:
connection = get_some_connection() # maybe from oursql
with connection.cursor() as cursor:
cursor.execute('some query')
I understand that after finishing cursor.close() will be executed automatically. What about exceptions? Must I put them inside?
connection = get_some_connection() # maybe from oursql
with connection.cursor() as cursor:
try:
cursor.execute('some query')
except IntegrityError, e:
# handle exceoption
Or is there a nicer way to handle them with the with statement?
with x as y: z() is basically syntactic sugar for:
y = x
y.__enter__()
try:
z()
finally:
if y.__exit__: y.__exit__()
This is not completely accurate, but that's the gist of it. Note that __exit__() will be passed exception information if an exception was thrown (see the docs) so you can "handle" an exception this way, but this will not keep the exception from being thrown up the call stack.
If you want to handle the exception gracefully and consume it, you need to use a try/catch block. It can be inside the with block or outside of it, as long as the try block is active when the exception is raised.
In the particular case of oursql,
with some_connection.cursor() as cursor:
do_something_with(cursor)
is equivalent to
cursor = some_connection.cursor()
try:
do_something_with(cursor)
except:
some_connection.rollback()
raise
else:
some_connection.commit()
finally:
cursor.close()
As you can see, what a with statement does depends on the context manager (e.g. some_connection.cursor()`).
with connection.cursor() as cursor:
try:
cursor.execute('some query')
except IntegrityError as e:
# handle exception
may or may not be the correct way to handle an IntegrityError -- you might want to handle the IntegrityError in some outer scope.
For example, if you had some generic function which logs queries such as
def log_query(query):
logger.info(query)
with connection.cursor() as cursor:
cursor.execute(query)
try:
log_query(query)
except IntegrityError as err:
# handler error
you may not want to handle IntegrityErrors inside log_query, but rather at a later stage.