Getting error messages from psycopg2 exceptions - python

This is my first project using psycopg2 extensively. I'm trying to find a way to extract the psql error message for whenever a connection attempt fails. I've tested the code below will work if all the variables are set correctly, however whenever an error condition occurs (e.g. user chooses a database that doesn't exist), Python will give me the following:
I am unable to connect to the database
None
Traceback (most recent call last):
File "./duplicate_finder.py", line 163, in <module>
main(sys.argv[1:])
File "./duplicate_finder.py", line 142, in main
print e.diag.message_detail
AttributeError: 'OperationalError' object has no attribute 'diag'
Is there a simple, catch-all method to catch whatever error message psql generates when a connection fails, or do I need to write except blocks for multiple psycopg2 exceptions?
Extract from my script:
import sys, getopt, os, time, csv, psycopg2
...
...
conn_string = "host=" + dbhost + " dbname=" + database + " user=" + dbuser + " password=" + dbpass
try:
conn = psycopg2.connect(conn_string)
except psycopg2.Error as e:
print "Unable to connect!"
print e.pgerror
print e.diag.message_detail
sys.exit(1)
else:
print "Connected!"
cur = conn.cursor()
cur.execute("SELECT id, lastname, firstname, location FROM test ORDER BY ctl_upd_dttm DESC;")
print cur.fetchone()
...
conn.close()

When I try to catch exceptions, e.pgerror is always None for connection errors. The following code block gets around this by directly printing 'e'.
try:
conn = psycopg2.connect(conn_string)
except psycopg2.OperationalError as e:
print('Unable to connect!\n{0}').format(e)
sys.exit(1)
else:
print('Connected!')
# do stuff
For example, in the case of password authentication failure:
Unable to connect!
FATAL: password authentication failed for user "user"
I realize this question is a year old but hopefully might help someone in the future

Ended up here because of
class 'psycopg2.errors.InvalidCursorName'
on Django. If that's your case, be sure to makemigrations

You are catching all exceptions with the base class psycopg2.Error. Your problem is probably that the diag attribute is new in psycopg2 2.5. What is your version?
>>> print psycopg2.__version__
2.5.1 (dt dec pq3 ext)

Since Python 3.9 (.removesuffix(), f-strings) I use
except psycopg2.Error as e:
log.error(f"{type(e).__module__.removesuffix('.errors')}:{type(e).__name__}: {str(e).rstrip()}")
if conn: conn.rollback()
where log is logger.
Connection errors lives directly in psycopg2 module while syntax errors in psycopg2.errors submodule. There is an unwanted newline at the end of every psycopg2 error message.

Related

CALL multiple procedures with python

I have a linux server and I would like to run a python script every day to run mysql procedures but I do not know how to run multiple procedures and put a condition if there is an error that it sends me an email with the description of the error. Here is my script with only one procedure:
#!/usr/bin/python
import MySQLdb
# Open database connection
db = MySQLdb.connect("localhost","user","password","bddname" )
# prepare a cursor object using cursor() method
cursor = db.cursor()
# execute SQL query using execute() method.
cursor.execute("CALL proc_commande_clts_detail7();")
# Fetch a single row using fetchone() method.
data = cursor.fetchone()
print "Database version : %s " % data
# disconnect from server
db.close()
Thank you for your help.
You can use callproc method to execute MySQL procedures
for proc_name in proc_name_list:
try:
result_args = cursor.callproc(proc_name, args=())
except Exception as e:
send_mail(str(e))
If you want to call multiple procedures, you can put callproc in some kind of loop and use try...catch for error handling.
wrapping them in try/except block and trigger email in except block?
Scheduling can be done through cron job.
import traceback
try:
cursor.execute("CALL proc_commande_clts_detail7();")
catch Exception as e:
email_msg = traceback.format_exc()
#send email logic

Synax error on db.close()

Im trying to use mysqldb in a python script.
Here is a part of the code from the script
cursor = db.cursor()
sql = """INSERT INTO location(`name`, `lat`, `long`, `guid`, `image`, `date`)VALUES(%(name)s, %(lat)s, %(long)s, %(guid)s, %(image)s, %(date)s)"""
try:
cursor.execute(sql)
db.commit()
db.close()
Im gettig a error on the db.close()
"db.close()
^
SyntaxError: invalid syntax"
So any suggestions here?
You cannot use try without except.
The proper way to ignore all errors is this:
try:
cursor.execute(sql)
db.commit()
except:
pass
db.close()
The error is with the try: - it's looking for an except: prior to the db.close.
You would make everyone live easier if you posted fully working examples.
I added some dummy code to you post to make it run
class fake:
def commit(self,):pass
def execute(self,sql):pass
def close(self,):pass
db =fake()
cursor=fake()
if 1:
sql = """INSERT INTO location(`name`, `lat`, `long`, `guid`, `image`, `date`)VALUES(%(name)s, %(lat)s, %(long)s, %(guid)s, %(image)s, %(date)s)"""
try:
cursor.execute(sql)
db.commit()
db.close()
If I run this I get:
$ python3 test.py
File "test.py", line 17
db.close()
^
IndentationError: unexpected unindent
$
Which is show you are missing the except clause in your example.
This isn't the error you report, perhaps you Syntax Error is in part of the code you haven't included in your question.
Ignoring the indentation errors in your code, you need to use either an except clause, a finally clause, or both with your try statement.
With a finally clause you can ensure that the db connection is closed:
try:
cursor.execute(sql)
db.commit()
finally:
db.close()
In practice it is worthwhile including an except clause so that the exception can be logged:
import traceback
try:
cursor.execute(sql)
db.commit()
except Exception as exc:
traceback.print_exc() # or whatever logging you require
raise # optionally re-raise the exception
finally:
db.close() # _always_ executed

Python MySQL INSERT query doesn't get executed

I'm currently writing a chat bot with plugin functionality and at the moment, I'm working on a permission system.
However, my insert query into my database somehow doesn't work. If I do it by hand, it works flawless.
Here's that piece of code... hopefully you see what I try here:
def dothis(message):
if message.content.split()[1].lower() == "op":
user = get_member_by_name(message, message.content.split()[2])
try:
pmcon = mdb.connect(db_server, db_user, db_pass, db_name)
pmcur = pmcon.cursor()
pmcur.execute("INSERT INTO users (username,userid,hasop) VALUES (\'{}\',\'{}\',{})".format(message.content.split()[2], user.id, "TRUE"))
except: mdb.Error, e:
print "Error %d: %s" % (e.args[0], e.args[1])
finally:
if pmcon:
pmcon.close()
I already tried putting the query in a string and let it be printed out, but I don't see an error.
Am I doing something wrong?
if your database connection is not configured to autocommit, you need to commit your statements:
pmcon.commit()
(after the execute statement.)

PostgreSQL and Python: Automated Password change

I've been trying to automate the installation of an Open Street Map Server since no one has published one yet and the task is pretty tedious. In order to do this I'm dealing with PostgreSQL databases in a script, which I left Python in charge of.
Here's the situation: Basically I'm running python scripts dealing with the database throughout bash code. I'm trying to make the install as user friendly as possible, part of that is automating the PostgreSQL setup. I prompt the user, in bash, for a password they would like to use for the postgres database that already comes with PostgreSQL. I then send their password as a command line argument to a Python script.
This is the part of the script I'm having problems with:
import psycopg2
import sys
con = None
code = sys.argv[1]
try:
con = psycopg2.connect(database='postgres', user='postgres')
cur = con.cursor()
cur.execute("ALTER USER postgres WITH PASSWORD '%s'" % code)
Basically: On the bottom line where I change the password for the postgres database, it doesn't actually work. I know this because later I am prompted in my bash script to enter the password and it results in an authentication failure.
I'm pretty new to this, so if anyone has some good advice, it would be greatly appreciated.
Please use the below code, you can generate random passwords and update them
NOTE: For this code to work, the readwrite1 user has to be present in database prior using this
from psycopg2 import Error
import psycopg2
import random
#password generation
def password_generator(password_length):
# maximum length of password needed
characters = string.ascii_letters + string.digits + '!##$%^&*()'
password = ''.join(random.choice(characters) for i in range(password_length))
return password
#define a function that handles and parses psycopg2 exceptions
def print_psycopg2_exception(err):
err_type, err_obj, traceback = sys.exc_info()
# get the line number when exception occured
line_num = traceback.tb_lineno
# print the connect() error
print ("\npsycopg2 ERROR:", err, "on line number:", line_num)
print ("psycopg2 traceback:", traceback, "-- type:", err_type)
# psycopg2 extensions.Diagnostics object attribute
print ("\nextensions.Diagnostics:", err.diag)
# print the pgcode and pgerror exceptions
print ("pgerror:", err.pgerror)
print ("pgcode:", err.pgcode, "\n")
def update_password():
password=password_generator(10)
try:
con = psycopg2.connect(host="host here",database="dbhere", user="username",password="password")
cur = con.cursor()
cur.execute("alter user readwrite1 with password %(password)s;", {'password': password})
con.commit()
except Exception as err:
# pass exception to function
print_psycopg2_exception(err)
exit(1)
finally:
print('password is: ', password)
if con:
con.close()
return password

How to avoid crashing python script when executing faulty SQL query?

I am using Python 2.7.6 and MySqldb module. I have a MySQL query that crashes sometimes. It is hard to catch the rootcause for the time being. How can I avoid crashing the python script when executing the SQL query? How can I make it fail gracefully?
The code looks like something;
cursor.execute(query)
You should throw an exception:
try:
cursor.execute(query)
except mysql.connector.Error:
"""your handling here"""
Here is a link to the MySQL Python Dev guide:
You can handle run time errors by using try except block.
At last you must use finally for cleanups like close the connection , rollback , free all the used resources etc.
Here is the example ,
import mysql.connector
try:
cnx = mysql.connector.connect(user='scott', database='employees')
cursor = cnx.cursor()
cursor.execute("SELECT * FORM employees") # Syntax error in query
cnx.close()
except mysql.connector.Error as err:
print("Something went wrong: {}".format(err))
finally:
# cleanup (close the connection, etc...)

Categories