[triangle-zpug] Python and psycopg
Tom Bryan
tbryan at python.net
Thu May 29 07:04:50 EDT 2003
We were discussing Python and PostreSQL at the meeting last night. I thought
that I'd go ahead and send some links and sample code since I've got it
available. I ripped this code from the EcoAccess project's unit tests, and I
didn't test the code after I removed it from its original file, so it may not
quite work.
The psycopg page is here: http://initd.org/software/psycopg
If you're on a Red Hat system, I have an RPM spec file for compiling and
wrapping the psycopg Python and compiled C code into a binary RPM. If you're
interested, send me an e-mail.
-- SQL script to create the table needed by the example below
create sequence ECOUSER_ID_SEQ start 1 increment 1 maxvalue 2147483647
minvalue 1 cache 10;
create table ECOUSER (
ECOUSER_ID int4 default nextval('ECOUSER_ID_SEQ') not null,
ECOUSER_NAME varchar(20) not null,
ECOUSER_PASSWORD varchar(20) not null,
ACTIVE_FLAG bool default FALSE not null,
LAST_NAME varchar(40),
FIRST_NAME varchar(40),
EMAIL varchar(40),
CHALLENGE_QUESTION text,
CHALLENGE_ANSWER text,
LOGIN_TOKEN int8,
LAST_LOGIN_DATE timestamp,
FAILED_LOGIN1 varchar(100),
FAILED_LOGIN2 varchar(100),
FAILED_LOGIN3 varchar(100),
FAILED_LOGIN4 varchar(100),
FAILED_LOGIN5 varchar(100),
constraint ecouser_pkey primary key (ECOUSER_ID),
constraint ecouser_uq1 unique (ECOUSER_NAME)
);
# Python code to insert and fetch some data
base_users = (
{'userId': 1, 'name':'darcy', 'password': 'peEhH7F4iC2l6',
'first_name': 'Darcy', 'last_name': 'Fitzwilliam',
'email': 'darcy at pemberly.org', 'active_flag':1},
{'userId': 2, 'name': 'lizzy', 'password': 'peEhH7F4iC2l6',
'first_name': 'Bennett', 'last_name': 'Elizabeth',
'email': 'lizzy at pemberly.org', 'active_flag': 1},
{'userId': 3, 'name': 'emma', 'password': 'IDta7uvnvGYCY',
'first_name': 'Woodhouse', 'last_name': 'Emma',
'email': 'emma at donwell.org', 'active_flag': 1 }
}
import psycopg
conn = psycopg.connect( 'dbname=ecoaccess' )
insert_cursor = conn.cursor()
for user in base_users:
# Note that we don't use % and interpolate the values ourselves
insert_cursor.execute(
"""INSERT into ECOUSER (ecouser_id, ecouser_name, ecouser_password,
first_name, last_name, email, active_flag) values
(%(userId)d, %(name)s,%(password)s, %(first_name)s,
%(last_name)s, %(email)s,%(active_flag)d::bool); """
, user )
conn.commit()
insert_cursor.close()
select_cursor = conn.cursor()
cursor.execute(
"""SELECT login_token, last_login_date from ECOUSER
where ECOUSER_NAME = %(name)s""", {'name': 'darcy'} )
results = cursor.fetchone()
select_cursor.close()
print results
conn.close()
One thing to note in this code. While I'm using the Python dictionary style
of interpolation in the string "%(key)s", I'm *not* actually interpolating
the dictionary values into the string and then passing it into pyscopg. I
pass the string and the dictionary into psycopg. The reason we do this is
that one hopes that the DB supports DB statement caching. So, basically, we
hope that the driver and the DB do something with that insert string that
looks like
"INSERT into ECOUSER (ecouser_id, ecouser_name, ecouser_password,
first_name, last_name, email, active_flag) values
(?,?,?,?,?,?,?);"
Then, for each call to insert, the driver would bind specific values to the
placeholders (the ? in this example). For large apps and DBs, this is
important because otherwise, in a tight code loop like that, the DB may have
to recreate the identical execution plan for each call to execute(). In
general, you'd like to write your SQL statements with placeholders and let
the driver do the interpolation of values into the string.
Unfortunately, the format in Python of the string you pass to the execute()
call varies between drivers. The DB API specifies several acceptable
formats. You can always pass a string with all of the values already
interpolated, but then you have to worry about DB quoting rules, and you
probably prevent the DB driver from doing any statement caching.
Did I mention at the meeting that I primarily do server-side, DB apps? :)
Finally, the "embedded" DB I was trying to remember at the meeting is SQLite.
See http://www.hwaci.com/sw/sqlite/index.html
There is a Python driver for the DB, but I haven't used it.
http://www.sourceforge.net/projects/pysqlite
Happy Pythoning,
---Tom
More information about the triangle-zpug
mailing list