Package: pgtrio
pgtrioThis is aTrio-native PostgreSQL interface library. It implements
the PostgreSQL wire protocol (both text and binary) in pure Python. It
automatically converts between common postgres/python types, and
supports adding custom codecs for other types. Transactions, cursors,
and prepared statements are also supported.Minimum Python version supported is 3.8.UsageYou can install pgtrio from pypi:pip install pgtrioTo use pgtrio, you either start by calling theconnectfunction or
thecreate_pool. The former returns a singleConnectionobject
while the latter returns aPoolobject that can be used to acquire
multipleConnectionobjects.importtrioimportpgtrioasyncdefmain():asyncwithpgtrio.connect('test')asconn:results=awaitconn.execute('select name, dob from users')forname,dobinresults:print(name,dob)trio.run(main)AConnectionobject can be used to execute queries, or create
transactions, cursors or prepared statements. OneConnectionobject
can only be used from a single Trio task. If you have multiple tasks,
you can use aPoolobject.importtrioimportpgtrioasyncdefinsert_rows(pool,start,end):asyncwithpool.acquire()asconn:foriinrange(start,end):results=awaitconn.execute('insert into numbers (n) values ($1)',i)asyncdefmain():asyncwithpgtrio.create_pool('test')aspool:asyncwithtrio.open_nursery()asnursery:nursery.start_soon(insert_rows,pool,0,10)nursery.start_soon(insert_rows,pool,10,20)trio.run(main)As you can see, you can also use query parameters and pass your
arguments to theexecutemethod after the query.pgtrioautomatically converts Python types to Postgres types. To see a list
of supported types, see the relevant section further in this document.TransactionsIn order to create a transaction, you can use theConnection.transactionmethod:importtrioimportpgtrioasyncdefmain():asyncwithpgtrio.connect('test')asconn:asyncwithconn.transaction()astr:awaitconn.execute("insert into users (name) values ('John Smith')")awaitconn.execute("insert into users (name) values ('Jane Smith')")trio.run(main)The transaction will be committed automatically when execution reaches
the end of theasync withblock. You can manually commit or rollback
the transaction at any point by callingawait tr.commit()orawait tr.rollbackat any point in the block. After any of those methods is
called, execution of the block will stop.Prepared StatementsIf you need to execute a single query multiple times, perhaps with
different arguments each time, you can use prepared statements.importtrioimportpgtrioasyncdefmain():asyncwithpgtrio.connect('test')asconn:stmt=awaitconn.prepare('insert into numbers (n) values ($1)')awaitstmt.execute(100)awaitstmt.execute(200)numbers=awaitconn.execute('select n from numbers order by n')assertnumbers==[(100,),(200,)]trio.run(main)Cursorspgtrioalso supports cursors for fetching large numbers of rows
without loading them all in memory.importtrioimportpgtrioasyncdefmain():asyncwithpgtrio.connect('test')asconn:asyncwithconn.transaction():cur=awaitconn.cursor('select * from users')chunk1=awaitcur.fetch(100)awaitcur.forward(50)chunk2=awaitcur.fetch(100)trio.run(main)Notice that a cursor must be used in a transaction block.Thefetchmethod fetches the number of requested rows. Theforwardmethod skips the given number of rows.You can also obtain a cursor from a prepared statement.importtrioimportpgtrioasyncdefmain():asyncwithpgtrio.connect('test')asconn:asyncwithconn.transaction():stmt=awaitconn.prepare('select * from users')cur=awaitstmt.cursor()chunk1=awaitcur.fetch(100)awaitcur.forward(50)chunk2=awaitcur.fetch(100)trio.run(main)Instead of using thefetchmethod you can also use iteration to read
from a cursor:importtrioimportpgtrioasyncdefmain():asyncwithpgtrio.connect('test')asconn:asyncwithconn.transaction():cur=awaitconn.cursor('select name, dob from users')asyncforname,dobincur:print(name,dob)trio.run(main)Supported Typespgtriocan automatically convert between the following
python/postgres types:postgres typepython typeboolboolbyteabytescharstrcidrIPv4Network/IPv6Networkdatedatetime.datefloat4floatfloat8floatinetIPv4Address/IPv6Addressintervaldatetime.timedeltajsonlist/dictjsonblist/dicttextstrtimedatetime.timetimetzdatetime.timetimestampdatetime.datetimetimestamptzdatetime.datetimevarcharstrDevelopmentYou can install development dependencies by setting up a virtualenv
(for example bypython3 -m venv venv && . venv/bin/activate) and
runningpip install -r requirements.txt.You can run unit tests by runningpython -m pytestinside a properly
setup virtualenv. Notice however that the tests currently only support
Linux and need postgres executables at a well-known location
(/usr/lib/postgresql).