Psycopg: bridging PostgreSQL and Python

img/psycopg.png

Boulder Linux Users Group, '2020-04-09'::date

Daniele Varrazzo

slides source

Presenter Notes

What are we talking about?

  • There is this language, Python 🐍
    • it's got all its types (strongly typed, dynamically typed)
  • and this database, PostgreSQL 🐘
    • yeah, not a great name. Let's call it Postgres
    • it's got a lot of different types too
  • You want to do something with the two 🐍↔️🐘
    • they are both very extendible
    • someone should map the two together

Presenter Notes

Mapping the two together

Psycopg!

  • Yeah, maybe questionable name too. 🤔
  • But now we sort of like it. 🤭

psycopg2

psycopg3

Presenter Notes

Basic usage

The roles of the main actors

import psycopg2                             # the driver
conn = psycopg2.connect("dbname=piro")      # the connection/session
cur = conn.cursor()                         # the cursor - holds a result

cur.execute("select 10 as a, 'foo' as b")   # sends command
cur.fetchone()                              # retrieve results
conn.commit()                               # controls the session

Different ways to consume data

cur.fetchone()      # returns one tuples
cur.fetchmany(n)    # returns a list of n tuples
cur.fetchall()      # returns a list with all the tuples
for t in cur:
    pass            # iterable of tuples

Presenter Notes

Data type mapping

Default data types mapping

Python PostgreSQL
None NULL
bool bool
int, long smallint, integer, bigint
float real, double
Decimal numeric
str, unicode varchar, text
date date
time time
datetime timestamp, timestamptz
timedelta interval
and many more...

Presenter Notes

Typecasting

img/pg-to-py.png

Typecasters have:

  • one or more OID
  • a name
  • a conversion function

Presenter Notes

Typecasting

img/pg-to-py.png

Customizing a typecaster

>>> cur.execute("select 123.45")
>>> cur.fetchone()
(Decimal('123.45'),)

>>> from psycopg2 import extensions as ext

>>> def num2float(s, cur):
...     if s is None:
...         return float(s)

>>> t = ext.new_type((1700,), "NUM2FLOAT", num2float)
>>> ext.register_type(t, cur)

>>> cur.execute("select 123.45")
>>> cur.fetchone()
(123.45,)

Presenter Notes

Adaptation

img/py-to-pg.png
>>> cur.execute("select '%s' || '%s'" % ('a', 'b'))
>>> cur.fetchone()
('ab',)

>>> cur.execute("select '%s' || '%s'" % ("O'Reilly", ' Books'))
Traceback (most recent call last):
  File "<ipython-input-29-720a7746fc83>", line 1, in <module>
    cur.execute("select '%s' || '%s'" % ("O'Reilly", ' Books'))
ProgrammingError: syntax error at or near "' || '"
LINE 1: select 'O'Reilly' || ' Books'
                        ^

>>> cur.execute("select %s || %s", ("O'Reilly", ' Books'))
>>> cur.fetchone()
("O'Reilly Books",)

Presenter Notes

Adaptation risk

>>> cur.execute("insert into students (name) values ('%s')" % name)
img/exploits_of_a_mom.png

Funny, but wrong conclusion:

>>> cur.execute("insert into students (name) values (%s)" , [name])
  • Look ma: no sanitizing database input here!
  • (You must not do it, we do it for you)

Presenter Notes

pushdemo.py architecture

img/pushdemo-diagram.png

Presenter Notes

Async notification demo

Using gevent, gevent-websocket, psycogreen

Note: the pushdemo.py script is not running.

 

 

 

Download the demo code

Presenter Notes

Async notification demo (offline)

img/pushdemo.png

Presenter Notes

Questions

  • Q: how can I install psycopg without needing a C compiler, install packages, etc?

    A: psycopg3 has only an optional C package and it's otherwise pure Python

  • Q: adaptation is kinda slow on my 1M entries array

    A: psycopg3 uses a different mechanism than adaptation and is much more performing with less objects created

  • Q: my database is SQL_ASCII and now it's a jumble of different encodings which don't make sense, but we are scraper guys so we have to

    A: psycopg3 allows you to use SQL_ASCII databases as a binary databases, encoding-agnostic

  • Q: ... A: You should really sponsor psycopg3! 💜

Presenter Notes

More questions?

Presenter Notes