Real time notifications from a Postgres function
Question:
I am trying to execute a function in Postgres which contains a number of Raise statements for debugging and info.
While I am able to connect to DB and get raise statements using conn.notices(). These are not printed to python console on a real time basis and are only available once the function execution is complete.
Is there a way to get these notifications real time, i.e. as they are printed to the postgres log?
Update: Tried [Asynchronous Notification][1] approach replacing raise info statements with pg_notify. Even then all the notifications are printed in the console in one go.
Answers:
In the RAISE case, PostgreSQL sends them in real time. You would have to dig into the guts of psycopg2 to figure out what it does with them.
I thought this would work, but I see that it doesn’t, it also saves them up until the end.
class append_printer():
def append(self, item) -> None:
print(item,flush=True)
conn = psycopg2.connect(...)
conn.notices=append_printer()
In the case of pg_notify, you are out of luck. By design, they are only sent once the sending transaction commits. And they are also not sent until the receiving end is between transactions.
If you upgrade to psycopg3, you can do this with a notice handler:
def log_notice(diag):
print(f"The server says: {diag.severity} - {diag.message_primary}")
conn = psycopg.connect(...)
conn.add_notice_handler(log_notice)
prints each message as it is received.
I am trying to execute a function in Postgres which contains a number of Raise statements for debugging and info.
While I am able to connect to DB and get raise statements using conn.notices(). These are not printed to python console on a real time basis and are only available once the function execution is complete.
Is there a way to get these notifications real time, i.e. as they are printed to the postgres log?
Update: Tried [Asynchronous Notification][1] approach replacing raise info statements with pg_notify. Even then all the notifications are printed in the console in one go.
In the RAISE case, PostgreSQL sends them in real time. You would have to dig into the guts of psycopg2 to figure out what it does with them.
I thought this would work, but I see that it doesn’t, it also saves them up until the end.
class append_printer():
def append(self, item) -> None:
print(item,flush=True)
conn = psycopg2.connect(...)
conn.notices=append_printer()
In the case of pg_notify, you are out of luck. By design, they are only sent once the sending transaction commits. And they are also not sent until the receiving end is between transactions.
If you upgrade to psycopg3, you can do this with a notice handler:
def log_notice(diag):
print(f"The server says: {diag.severity} - {diag.message_primary}")
conn = psycopg.connect(...)
conn.add_notice_handler(log_notice)
prints each message as it is received.