2004-11-20 06:18:42 +03:00
|
|
|
psycopg asynchronous API
|
|
|
|
************************
|
|
|
|
|
2005-11-29 15:01:46 +03:00
|
|
|
** Important: async quaeries are not enabled for 2.0 **
|
|
|
|
|
2004-11-20 06:18:42 +03:00
|
|
|
Program code can initiate an asynchronous query by passing an 'async=1' flag
|
|
|
|
to the .execute() method. A very simple example, from the connection to the
|
|
|
|
query:
|
|
|
|
|
|
|
|
conn = psycopg.connect(database='test')
|
|
|
|
curs = conn.cursor()
|
|
|
|
curs.execute("SEECT * from test WHERE fielda > %s", (1971,), async=1)
|
|
|
|
|
|
|
|
From then on any query on other cursors derived from the same connection is
|
|
|
|
doomed to fail (and raise an exception) until the original cursor (the one
|
|
|
|
executing the query) complete the asynchronous operation. This can happen in
|
|
|
|
a number of different ways:
|
|
|
|
|
|
|
|
1) one of the .fetchXXX() methods is called, effectively blocking untill
|
|
|
|
data has been sent from the backend to the client, terminating the
|
|
|
|
query.
|
|
|
|
|
|
|
|
2) .cancel() is called. This method tries to abort the current query and
|
|
|
|
will block until the query is aborted or fully executed. The return
|
|
|
|
value is True if the query was successfully aborted or False if it
|
|
|
|
was executed. Query result are discarded in both cases.
|
|
|
|
|
|
|
|
3) .execute() is called again on the same cursor (.execute() on a
|
|
|
|
different cursor will simply raise an exception.) This waits for the
|
|
|
|
complete execution of the current query, discard any data and execute
|
|
|
|
the new one.
|
|
|
|
|
|
|
|
Note that calling .execute() two times in a row will not abort the former
|
|
|
|
query and will temporarily go to synchronous mode until the first of the two
|
|
|
|
queries is executed.
|
|
|
|
|
|
|
|
Cursors now have some extra methods that make them usefull during
|
|
|
|
asynchronous queries:
|
|
|
|
|
|
|
|
.fileno()
|
|
|
|
Returns the file descriptor associated with the current connection and
|
|
|
|
make possible to use a cursor in a context where a file object would be
|
|
|
|
expected (like in a select() call.)
|
|
|
|
|
|
|
|
.isbusy()
|
|
|
|
Returns True if the backend is still processing the query or false if
|
|
|
|
data is ready to be fetched (by one of the .fetchXXX() methods.)
|
|
|
|
|
|
|
|
A code snippet that shows how to use the cursor object in a select() call:
|
|
|
|
|
|
|
|
import psycopg
|
|
|
|
import select
|
|
|
|
|
|
|
|
conn = psycopg.connect(database='test')
|
|
|
|
curs = conn.cursor()
|
|
|
|
curs.execute("SEECT * from test WHERE fielda > %s", (1971,), async=1)
|
|
|
|
|
|
|
|
# wait for input with a maximum timeout of 5 seconds
|
|
|
|
query_ended = False
|
|
|
|
while not query_ended:
|
|
|
|
rread, rwrite, rspec = select([cursor, another_file], [], [], 5)
|
|
|
|
if not cursor.isbusy():
|
|
|
|
query_ended = True
|
|
|
|
# manage input from other sources like other_file, etc.
|
|
|
|
print "Query Results:"
|
|
|
|
for row in cursor:
|
|
|
|
print row
|