mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-02-07 12:50:32 +03:00
Added documentation for the new asynchronous support.
This commit is contained in:
parent
d197346ce3
commit
6aaa50703e
|
@ -246,88 +246,83 @@ Running the script and executing the command :sql:`NOTIFY test` in a separate
|
||||||
|
|
||||||
|
|
||||||
.. index::
|
.. index::
|
||||||
double: Asynchronous; Query
|
double: Asynchronous; Connection
|
||||||
|
|
||||||
.. _asynchronous-queries:
|
.. _async-support:
|
||||||
|
|
||||||
Asynchronous queries
|
Asynchronous support
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
.. warning::
|
.. versionadded:: 2.2.0
|
||||||
|
|
||||||
Psycopg support for asynchronous queries is still experimental and the
|
Psycopg can issue asynchronous queries to a Postgresql database. An asynchronous
|
||||||
informations reported here may be out of date.
|
communication style is estabilished passing the parameter *async*\=1 to the
|
||||||
|
`~psycopg2.connect()` function: the returned connection will work in
|
||||||
|
asynchronous mode.
|
||||||
|
|
||||||
Discussion, testing and suggestions are welcome.
|
In asynchronous mode, a Psycopg connection will rely on the caller to poll for
|
||||||
|
the socket file descriptor ready to accept data or a query result ready to be
|
||||||
|
read from the server. The caller can use the method `~cursor.fileno()` to get
|
||||||
|
the connection file descriptor and `~cursor.poll()` to make communication
|
||||||
|
proceed. An application can use a loop like the one below to transfer data
|
||||||
|
between the client and the server::
|
||||||
|
|
||||||
Program code can initiate an asynchronous query by passing an ``async=1`` flag
|
def wait(conn_or_cur):
|
||||||
to the `~cursor.execute()` or `~cursor.callproc()` cursor methods. A
|
while 1:
|
||||||
very simple example, from the connection to the query::
|
state = conn_or_cur.poll()
|
||||||
|
if state == psycopg2.extensions.POLL_OK:
|
||||||
|
break
|
||||||
|
elif state == psycopg2.extensions.POLL_WRITE:
|
||||||
|
select.select([], [conn_or_cur.fileno()], [])
|
||||||
|
elif state == psycopg2.extensions.POLL_READ:
|
||||||
|
select.select([conn_or_cur.fileno()], [], [])
|
||||||
|
else:
|
||||||
|
raise psycopg2.OperationalError("poll() returned %s" % state)
|
||||||
|
|
||||||
conn = psycopg2.connect(database='test')
|
After `!poll()` has returned `~psycopg2.extensions.POLL_OK`, the results are
|
||||||
|
available in the cursor for regular reading::
|
||||||
|
|
||||||
|
curs.execute("SELECT * FROM foo;")
|
||||||
|
wait(curs)
|
||||||
|
for record in curs:
|
||||||
|
# use it...
|
||||||
|
|
||||||
|
The same loop should also be used to accomplish a connection with the server:
|
||||||
|
the connection is usable only after `connection.poll()` has returned `!POLL_OK`.
|
||||||
|
The `!connection` has a `~connection.fileno()` method too, so it is possible to
|
||||||
|
use the same interface for the wait loop::
|
||||||
|
|
||||||
|
conn = psycopg2.connect(database='test', async=1)
|
||||||
|
wait(conn)
|
||||||
|
# Now you can have a cursor.
|
||||||
curs = conn.cursor()
|
curs = conn.cursor()
|
||||||
curs.execute("SELECT * from test WHERE fielda > %s", (1971,), async=1)
|
|
||||||
|
|
||||||
From then on any query on other cursors derived from the same connection is
|
Notice that there are a few other requirements to be met in order to have a
|
||||||
doomed to fail (and raise an exception) until the original cursor (the one
|
completely non-blocking connection attempt: see the libpq documentation for
|
||||||
executing the query) complete the asynchronous operation. This can happen in
|
|PQconnectStart|_.
|
||||||
a number of different ways:
|
|
||||||
|
|
||||||
1) one of the `!fetch*()` methods is called, effectively blocking until
|
.. |PQconnectStart| replace:: `!PQconnectStart()`
|
||||||
data has been sent from the backend to the client, terminating the query.
|
.. _PQconnectStart: http://www.postgresql.org/docs/8.4/static/libpq-connect.html#AEN33199
|
||||||
|
|
||||||
2) `connection.cancel()` is called. This method tries to abort the
|
When an asynchronous query is being executed, `connection.executing()` returns
|
||||||
current query and will block until the query is aborted or fully executed.
|
`True`. Two cursors can't execute concurrent queries on the same asynchronous
|
||||||
The return value is ``True`` if the query was successfully aborted or
|
connection.
|
||||||
``False`` if it was executed. Query result are discarded in both cases.
|
|
||||||
|
|
||||||
3) `~cursor.execute()` is called again on the same cursor
|
There are several limitations in using asynchronous connections: the connection
|
||||||
(`!execute()` on a different cursor will simply raise an exception).
|
is always in :ref:`autocommit <autocommit>` mode and it is not possible to
|
||||||
This waits for the complete execution of the current query, discard any
|
change it using `~connection.set_isolation_level()`. So transaction are not
|
||||||
data and execute the new one.
|
started at each query and is not possible to use methods `~connection.commit()`
|
||||||
|
and `~connection.rollback()`: you can manually control transactions using
|
||||||
|
`~cursor.execute()` to send commands :sql:`BEGIN`, :sql:`COMMIT` and
|
||||||
|
:sql:`ROLLBACK`.
|
||||||
|
|
||||||
Note that calling `!execute()` two times in a row will not abort the
|
With asynchronous connections it is also not possible to use
|
||||||
former query and will temporarily go to synchronous mode until the first of
|
`~connection.set_client_encoding()`, `~cursor.executemany()`, :ref:`large
|
||||||
the two queries is executed.
|
objects <large-objects>`, :ref:`named cursors <server-side-cursors>`.
|
||||||
|
|
||||||
Cursors now have some extra methods that make them useful during
|
:ref:`COPY commands <copy>` are not supported either in asynchronous mode, but
|
||||||
asynchronous queries:
|
this will be probably implemented in a future release.
|
||||||
|
|
||||||
`~cursor.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).
|
|
||||||
|
|
||||||
`~cursor.isready()`
|
|
||||||
Returns ``False`` if the backend is still processing the query or ``True``
|
|
||||||
if data is ready to be fetched (by one of the `!fetch*()` methods).
|
|
||||||
|
|
||||||
.. index::
|
|
||||||
single: Example; Asynchronous query
|
|
||||||
|
|
||||||
A code snippet that shows how to use the cursor object in a `!select()`
|
|
||||||
call::
|
|
||||||
|
|
||||||
import psycopg2
|
|
||||||
import select
|
|
||||||
|
|
||||||
conn = psycopg2.connect(database='test')
|
|
||||||
curs = conn.cursor()
|
|
||||||
curs.execute("SELECT * 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([curs, another_file], [], [], 5)
|
|
||||||
|
|
||||||
if curs.isready():
|
|
||||||
query_ended = True
|
|
||||||
|
|
||||||
# manage input from other sources like other_file, etc.
|
|
||||||
|
|
||||||
print "Query Results:"
|
|
||||||
for row in curs:
|
|
||||||
print row
|
|
||||||
|
|
||||||
|
|
||||||
.. testcode::
|
.. testcode::
|
||||||
|
|
|
@ -314,3 +314,37 @@ The ``connection`` class
|
||||||
.. _lo_import: http://www.postgresql.org/docs/8.4/static/lo-interfaces.html#AEN36307
|
.. _lo_import: http://www.postgresql.org/docs/8.4/static/lo-interfaces.html#AEN36307
|
||||||
|
|
||||||
.. versionadded:: 2.0.8
|
.. versionadded:: 2.0.8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. rubric:: Methods related to asynchronous support.
|
||||||
|
|
||||||
|
.. seealso:: :ref:`Asynchronous support <async-support>`.
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: issync()
|
||||||
|
|
||||||
|
Return `True` if the connection is synchronous, `False` if asynchronous.
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: poll()
|
||||||
|
|
||||||
|
Used during an asynchronous connection attempt, make communication
|
||||||
|
proceed if it wouldn't block.
|
||||||
|
|
||||||
|
Return one of the constants defined in :ref:`poll-constants`. If it
|
||||||
|
returns `~psycopg2.extensions.POLL_OK` the connection has been
|
||||||
|
estabilished. Otherwise wait until the file descriptor is ready as
|
||||||
|
explained in :ref:`async-support`.
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: fileno()
|
||||||
|
|
||||||
|
Return the file descriptor associated with the connection to read the
|
||||||
|
status during asynchronous communication.
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: executing()
|
||||||
|
|
||||||
|
Return `True` if the connection is executing an asynchronous operation.
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ The ``cursor`` class
|
||||||
.. rubric:: Commands execution methods
|
.. rubric:: Commands execution methods
|
||||||
|
|
||||||
|
|
||||||
.. method:: execute(operation [, parameters] [, async])
|
.. method:: execute(operation [, parameters])
|
||||||
|
|
||||||
Prepare and execute a database operation (query or command).
|
Prepare and execute a database operation (query or command).
|
||||||
|
|
||||||
|
@ -121,16 +121,6 @@ The ``cursor`` class
|
||||||
The method returns `None`. If a query was executed, the returned
|
The method returns `None`. If a query was executed, the returned
|
||||||
values can be retrieved using |fetch*|_ methods.
|
values can be retrieved using |fetch*|_ methods.
|
||||||
|
|
||||||
If `async` is ``True``, query execution will be asynchronous:
|
|
||||||
the function returns immediately while the query is executed by the
|
|
||||||
backend. Use the `~cursor.isready()` method to see if the data is
|
|
||||||
ready for return via |fetch*|_ methods. See
|
|
||||||
:ref:`asynchronous-queries`.
|
|
||||||
|
|
||||||
.. extension::
|
|
||||||
|
|
||||||
The `async` parameter is a Psycopg extension to the |DBAPI|.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: mogrify(operation [, parameters])
|
.. method:: mogrify(operation [, parameters])
|
||||||
|
|
||||||
|
@ -159,7 +149,7 @@ The ``cursor`` class
|
||||||
the `~cursor.execute()` method.
|
the `~cursor.execute()` method.
|
||||||
|
|
||||||
|
|
||||||
.. method:: callproc(procname [, parameters] [, async])
|
.. method:: callproc(procname [, parameters])
|
||||||
|
|
||||||
Call a stored database procedure with the given name. The sequence of
|
Call a stored database procedure with the given name. The sequence of
|
||||||
parameters must contain one entry for each argument that the procedure
|
parameters must contain one entry for each argument that the procedure
|
||||||
|
@ -170,16 +160,6 @@ The ``cursor`` class
|
||||||
The procedure may also provide a result set as output. This must then
|
The procedure may also provide a result set as output. This must then
|
||||||
be made available through the standard |fetch*|_ methods.
|
be made available through the standard |fetch*|_ methods.
|
||||||
|
|
||||||
If `async` is ``True``, procedure execution will be asynchronous:
|
|
||||||
the function returns immediately while the procedure is executed by
|
|
||||||
the backend. Use the `~cursor.isready()` method to see if the
|
|
||||||
data is ready for return via |fetch*|_ methods. See
|
|
||||||
:ref:`asynchronous-queries`.
|
|
||||||
|
|
||||||
.. extension::
|
|
||||||
|
|
||||||
The `async` parameter is a Psycopg extension to the |DBAPI|.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: setinputsizes(sizes)
|
.. method:: setinputsizes(sizes)
|
||||||
|
|
||||||
|
@ -400,29 +380,6 @@ The ``cursor`` class
|
||||||
|DBAPI|.
|
|DBAPI|.
|
||||||
|
|
||||||
|
|
||||||
.. method:: isready()
|
|
||||||
|
|
||||||
Return ``False`` if the backend is still processing an asynchronous
|
|
||||||
query or ``True`` if data is ready to be fetched by one of the
|
|
||||||
|fetch*|_ methods. See :ref:`asynchronous-queries`.
|
|
||||||
|
|
||||||
.. extension::
|
|
||||||
|
|
||||||
The `isready()` method is a Psycopg extension to the |DBAPI|.
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: fileno()
|
|
||||||
|
|
||||||
Return 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). See
|
|
||||||
:ref:`asynchronous-queries`.
|
|
||||||
|
|
||||||
.. extension::
|
|
||||||
|
|
||||||
The `fileno()` method is a Psycopg extension to the |DBAPI|.
|
|
||||||
|
|
||||||
|
|
||||||
.. attribute:: tzinfo_factory
|
.. attribute:: tzinfo_factory
|
||||||
|
|
||||||
The time zone factory used to handle data types such as
|
The time zone factory used to handle data types such as
|
||||||
|
@ -434,6 +391,33 @@ The ``cursor`` class
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. rubric:: Methods related to asynchronous support.
|
||||||
|
|
||||||
|
.. extension::
|
||||||
|
|
||||||
|
:ref:`Asynchronous support <async-support>` is a Psycopg extension to
|
||||||
|
the |DBAPI|.
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: poll()
|
||||||
|
|
||||||
|
Used during asynchronous queries, make asynchronous communication
|
||||||
|
proceed if it wouldn't block.
|
||||||
|
|
||||||
|
Return `~psycopg2.extensions.POLL_OK` if the query has been fully
|
||||||
|
processed, `~psycopg2.extensions.POLL_READ` if the query has been sent
|
||||||
|
and the application should be waiting for the result to arrive or
|
||||||
|
`~psycopg2.extensions.POLL_WRITE` is the query is still being sent.
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: fileno()
|
||||||
|
|
||||||
|
Return the file descriptor associated with the current connection to
|
||||||
|
make possible to use a cursor in a context where a file object would
|
||||||
|
be expected (like in a `select()` call).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. rubric:: COPY-related methods
|
.. rubric:: COPY-related methods
|
||||||
|
|
||||||
.. extension::
|
.. extension::
|
||||||
|
|
|
@ -21,6 +21,8 @@ functionalities defined by the |DBAPI|_.
|
||||||
`!connect()` function using the `connection_factory` parameter.
|
`!connect()` function using the `connection_factory` parameter.
|
||||||
See also :ref:`subclassing-connection`.
|
See also :ref:`subclassing-connection`.
|
||||||
|
|
||||||
|
Subclasses should have constructor signature :samp:`({dsn}, {async}=0)`.
|
||||||
|
|
||||||
For a complete description of the class, see `connection`.
|
For a complete description of the class, see `connection`.
|
||||||
|
|
||||||
.. class:: cursor
|
.. class:: cursor
|
||||||
|
@ -80,11 +82,11 @@ functionalities defined by the |DBAPI|_.
|
||||||
|
|
||||||
.. method:: truncate(len=0)
|
.. method:: truncate(len=0)
|
||||||
|
|
||||||
.. versionadded:: 2.0.15
|
.. versionadded:: 2.2.0
|
||||||
|
|
||||||
Truncate the lobject to the given size.
|
Truncate the lobject to the given size.
|
||||||
|
|
||||||
The method will only be available if psycopg has been built against libpq
|
The method will only be available if Psycopg has been built against libpq
|
||||||
from PostgreSQL 8.3 or later and can only be used with PostgreSQL servers
|
from PostgreSQL 8.3 or later and can only be used with PostgreSQL servers
|
||||||
running these versions. It uses the |lo_truncate|_ libpq function.
|
running these versions. It uses the |lo_truncate|_ libpq function.
|
||||||
|
|
||||||
|
@ -443,6 +445,40 @@ can be read from the `~connection.status` attribute.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. index::
|
||||||
|
pair: Poll status; Constants
|
||||||
|
|
||||||
|
.. _poll-constants:
|
||||||
|
|
||||||
|
Poll constants
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. versionadded:: 2.2.0
|
||||||
|
|
||||||
|
These values can be returned by `connection.poll()` and `cursor.poll()` during
|
||||||
|
asynchronous communication. See :ref:`async-support`.
|
||||||
|
|
||||||
|
.. data:: POLL_OK
|
||||||
|
|
||||||
|
The data is available (or the file descriptor is ready for writing): there
|
||||||
|
is no need to block anymore.
|
||||||
|
|
||||||
|
.. data:: POLL_READ
|
||||||
|
|
||||||
|
Upon receiving this value, the callback should wait for the connection
|
||||||
|
file descriptor to be ready *for reading*. For example::
|
||||||
|
|
||||||
|
select.select([conn.fileno()], [], [])
|
||||||
|
|
||||||
|
.. data:: POLL_WRITE
|
||||||
|
|
||||||
|
Upon receiving this value, the callback should wait for the connection
|
||||||
|
file descriptor to be ready *for writing*. For example::
|
||||||
|
|
||||||
|
select.select([], [conn.fileno()], [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Additional database types
|
Additional database types
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ The module interface respects the standard defined in the |DBAPI|_.
|
||||||
single: Port; Connection
|
single: Port; Connection
|
||||||
single: DSN (Database Source Name)
|
single: DSN (Database Source Name)
|
||||||
|
|
||||||
.. function:: connect(dsn or params[, connection_factory])
|
.. function:: connect(dsn or params [, connection_factory] [, async=0])
|
||||||
|
|
||||||
Create a new database session and return a new `connection` object.
|
Create a new database session and return a new `connection` object.
|
||||||
|
|
||||||
|
@ -40,15 +40,18 @@ The module interface respects the standard defined in the |DBAPI|_.
|
||||||
|
|
||||||
.. __: http://www.postgresql.org/docs/8.4/static/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS
|
.. __: http://www.postgresql.org/docs/8.4/static/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS
|
||||||
|
|
||||||
Using the `connection_factory` parameter a different class or
|
Using the *connection_factory* parameter a different class or
|
||||||
connections factory can be specified. It should be a callable object
|
connections factory can be specified. It should be a callable object
|
||||||
taking a `dsn` argument. See :ref:`subclassing-connection` for
|
taking a *dsn* argument. See :ref:`subclassing-connection` for
|
||||||
details.
|
details.
|
||||||
|
|
||||||
|
Using *async*\=1 an asynchronous connection will be created: see
|
||||||
|
:ref:`async-support` to know about advantages and limitations.
|
||||||
|
|
||||||
.. extension::
|
.. extension::
|
||||||
|
|
||||||
The `connection_factory` parameter is a Psycopg extension to the
|
The parameters *connection_factory* and *async* are Psycopg extensions
|
||||||
|DBAPI|.
|
to the |DBAPI|.
|
||||||
|
|
||||||
|
|
||||||
.. data:: apilevel
|
.. data:: apilevel
|
||||||
|
|
Loading…
Reference in New Issue
Block a user