Tải bản đầy đủ - 0 (trang)
Chapter 17.  Using PostgreSQL with Python

Chapter 17.  Using PostgreSQL with Python

Tải bản đầy đủ - 0trang

Python/PostgreSQLInterfaceArchitecture

PostgreSQLusuallycomespackagedwithaPythoninterface

namedPyGreSQL.PyGreSQLisasmallcollectionofclassesand

functionsthatenableaPythonapplicationtointeractwitha

PostgreSQLdatabase.Forthelastseveralreleases,PyGreSQL

hasincludedanalternateinterface,whichwewillcalltheDBAPI.TheDB-APIwasdesignedtoofferaportableinterface

betweenPythonapplicationsandavarietyofrelational

databases.InthecaseofPostgreSQL,theDB-APIisdistributed

asawrapperaroundthePyGreSQLinterface.So,whenyour

PythonapplicationcallsaDB-APIfunction,theDB-APIlayer

translatestherequestintoaPyGreSQLfunctioncall.Theresults

fromeachDB-APIfunctioncallaretranslatedfromPyGreSQL

formbackintoDB-APIformandthenreturnedtoyour

application.

InadditiontothePyGreSQLinterface(andthePyGreSQL/DBAPIwrapper),thereareatleasttwootherimplementationsof

theDB-APIwrittenforPostgreSQL.Thefirst,PsycoPg(isn'tthat

agreatname?),canbefoundat

http://initd.org/Software/psycopg.Thesecond,PoPylivesat

http://popy.sourceforge.net.Allthreeoftheseinterfacesare

DB-API-compliantthat'sgoodnewsbecauseyoucanswitch

betweenimplementationswithoutmajorchangestoyour

application.

Thealternateimplementations(PyscoPgandPoPy)havebeen

designedtomaximizeperformance.Theinterfacedistributed

withPostgreSQL(PyGreSQL)wasimplementedasawrapper,so

itprobablywon'tbequiteasfastastheothertwo;butwith

PyGreSQL,youcanpickandchoosebetweenthetwointerface

layers.

Inthischapter,I'lldescribetheDB-APIinterfacebetween

PythonandPostgreSQL,butnotPyGreSQL.Applicationswritten



totheDB-APIspecificationcanconnecttodifferentdatabases;

applicationswrittenusingPyGreSQLcannot.ThePostgreSQL

Programmer'sGuidecontainsadescriptionoftheunderlying(or

alternate,dependingonyourperspective)PyGreSQLinterface.



Prerequisites

Ifyouwanttotrytheexamplesinthischapter,you'llprobably

needtoinstallafewextrapiecesofsoftware.Youwillobviously

needPythonandPostgreSQL.You'llalsoneedthePyGreSQL

interface.

IfyouareinstallingPostgreSQLfromRPMs,youwillfindthe

PyGreSQLinterfaceinthepostgresql-pythonRPM.

IfyouarebuildingPostgreSQLfromasourcedistribution,you

mustincludethe--with-pythonflagwhenyourunconfigure.

Whenyourunmakeinstall,thefollowingfileswillbe

installed[1]:

[1]Theexactpathnameswilldependonyourconfiguration,butthefilenamesshouldbethe

same.



/usr/lib/python1.5/site-packages/_pgmodule.so

/usr/lib/python1.5/site-packages/pg.py

/usr/lib/python1.5/site-packages/pgdb.py

IfyouintendtousethePython-DBAPI(whichIwould

recommend),youwillalsoneedthemxextensionspackage

fromEgenix(http://www.egenix.com/files/python/).

SomeoftheexamplesinthischaptermakeuseoftheTkinter

GUItoolkit(moreonthatlater).Tkinterisusuallydistributed

withPython,butyouwillalsoneedtheTktablemodule.Youcan

findTktable.pyatourwebsite:

http://www.conjectrix.com/pgbook/python.



Client1ConnectingtotheServer

TointeractwithaPostgreSQLserverusingPython'sDB-API,you

mustfirstimportthepgdbmodule.Thismoduledefinesafew

exceptionclasses(we'lltalkaboutexceptionsalittlelater),two

classes(pgdbCnxandpgdbCursor),andasinglemodule

function.

Thepgdb.connect()functionreturnsaconnectionobject(an

instanceofclasspgdbCnx).Thisfunctionactuallycomesintwo

flavors:

pgdb.connect(dsn)

pgdb.connect(dsn=dsn,

user=user,

password=password,

host=host,

database=dbname)

Inthefirstflavor,thedsnisexpectedtobeastringoftheform:

host:database:user:password:opt:tty

Therulesforcomposingavaliddsnareabitcomplex.Inthe

simplestcase,youcanspecifyallconnectionpropertiesinthe

ordershown:



"davinci:movies:bruce:cows:-fi:/dev/tty"

Youcanomitleadingproperties,butyoumustincludethe

propernumberofdelimiters(thatis,colons):

"::bruce:cows:-fi:/dev/tty"#omithostanddatabase

Youcanomitpropertiesinthemiddleofthedsn,butagain,you

mustincludethepropernumberofcolons:

"davinci:movies:::-fi:/dev/tty"#omituserandpassword

Youcanomittrailingproperties,inwhichcasetheextra

delimitersareoptional:

"davinci:movies:bruce:::"#omitpassword,opt

"davinci:movies:bruce"#ditto

Inthesecondflavor,youshouldpasseachparameterusing

Python'snamedparametermechanism.Forexample:

pgdb.connect(host='davinci',user='bruce')

pgdb.connect(host='davinci:5432',user='bruce')

pgdb.connect(user='bruce',

password='cows',



host='davinci',

database='movies')

Theorderinwhichtheparametersappearisunimportantwhen

youusenamedparameters.Alsonotice,inthesecondexample,

thatyoucanincludeaportnumberinthehostparameterjust

separatethehostnameandportnumberwithacolon.

Youcanalsocombinethefirstandsecondforms:



pgdb.connect(dsn="davinci:movies",user='bruce',password='c

Inthiscase,wehaveusedthedsntospecifythehostnameand

database,andnamedparameterstospecifytheusernameand

password.Ifyouhaveduplicateproperties,thenamed

parameterstakeprecedenceoverthepropertiesspecifiedinthe

dsn,forexample:

pgdb.connect(dsn="davinci:movies:sheila",

user="bruce",

password="cows")

Inthiscase,wespecifiedausername(sheila)inthedsn,but

wehavealsosuppliedausername(bruce)withtheuser

namedparameter;wewillconnectasuserbruce.

ThePostgreSQLimplementationoftheDB-APIeventuallyends

upusingthelibpqlibrary(PostgreSQL'sClanguageAPI)todo

allthelow-levelcommunicationswork.Ifyou'vereadsomeof



thepreviouschapters,youmightbethinkingthatyoucanuse

environmentvariables(suchasPGDATABASE)tosupplydefault

valuesforconnectionproperties(refertoTable8.2fora

descriptionoftheconnection-relatedenvironmentvariables).

Youmaybeableto,butforonlythreeoftheconnection

properties:PGHOST,PGPORT,andPGUSER.Anapparentbugin

PythonpreventsyoufromusingPGOPTIONS,PGTTY,

PGDATABASE,andPGPASSWORD.Thisproblemmaybefixedin

newerversionsofPython,sobesuretotestthefeatureifyou

needit.

Afteryouhavesuccessfullyconnected,pgdb.connect()returns

aconnectionobject.We'lllookatsomeofthethingsthatyou

candowithaconnectionobjectabitlater.Fornow,let's

developasimpleclientthatestablishesaconnectiontoa

PostgreSQLserver.

Listing17.1showsthefileclient1.py.Thefirstlinetellsthe

operatingsystemwhichinterpretertousetorunthisscript.If

yourcopyofPythonisstoredinadifferentlocation,youshould

adjustthislinetoreflectthecorrectdirectory.Ifyouarenewto

Python,youmaybesurprisedtofindthattherearenoblock

delimiters(curlybracesorBEGIN/ENDpairs)tomarkthe

boundariesofcomplexstatements.Pythonusesindentationto

indicateblockboundaries.



Listing17.1client1.py



1#!/usr/bin/python

2#

3#Filename:client1.py

4



5importpgdb

6

7connection=pgdb.connect(database="movies",

8user="bruce",

9password="cows")

10

11printconnection

Atline5,youimportthepgdbmodule.Whenyouimporta

module,alltheclassesandfunctionsinthatmodulebecome

availableforyoutouse.Next,atlines7,8,and9youusethe

pgdb.connect()functiontoestablishaconnectiontothe

moviesdatabase.Finally,youprinttheconnectionobject

returnedbypgdb.connect().

Let'srunthisclientapplicationtoseewhataconnectionobject

lookslike:

$chmoda+xclient1.py

$./client1.py



$

Thesinglelineofoutputreallydoesn'ttellyouanythinguseful

otherthanyourprogramdidsomething.Now,shutdownthe



postmasterandrunclient1.pyagainsoyoucanseehowan

errorisreported:

$pg_ctlstop

waitingforpostmastertoshutdown......done

$./client1.py

Traceback(innermostlast):

File"./client1.py",line9,in?

password="cows")



File"/usr/lib/python1.5/site-packages/pgdb.py",line376,in

user=dbuser,passwd=dbpasswd)



pg.error:couldnotconnecttoserver:Nosuchfileordire

Istheserverrunninglocallyandaccepting



connectionsonUnixdomainsocket"/tmp/.s.PGSQL.5432"?

Don'tyoujustlovebeingassaultedbyerrormessageslikethis?

Ifyou'reaprogrammer,youprobablyappreciatethelevelof

detailandacompletecontext,butouruserstendtogetupset

whentheyseesmokeandflames.Let'scleanthisup.



Client2AddingErrorChecking

Ifyoulookbacktoline7ofListing17.1,you'llnoticethatyou

callpgdb.connect()toconnecttoaPostgreSQLserver.If

anythinggoeswrongduringthisfunctioncall,Pythonwillprinta

stacktraceandaborttheprogram.

Ifyouwanttointerceptaconnectionerror,youmustwrapthe

calltopgdb.connect()inatry/exceptblock.ThePythonDBAPIspecificationdefinesahierarchyofexceptiontypesthata

conformingimplementationmaythrow.Themostgeneral

exceptiontypeisStandardError.AllotherDB-APIexceptions

arederived(directlyorindirectly)fromStandardError.You

mightthinkthattocatchaconnectionfailure,youcangetaway

withcatchingStandardErrorexceptions.Let'stryittosee

whathappens.(Warning:Yourredherringalarmshouldbe

soundingaboutnow.)

Listing17.2showsclient2a.py.Callpgdb.connect()insideof

atry/exceptblockandcatchanyexceptionsderivedfrom

StandardError(includingStandardError).



Listing17.2client2a.py



1#!/usr/bin/python

2#

3#Filename:client2a.py

4

5importpgdb



6

7try:

8connection=pgdb.connect(database="movies",

9user="bruce",

10password="cows")

11printconnection

12

13exceptStandardError,e:

14printstr(e)

Now,let'srunthisclienttoseewhataniceerrormessage

mightlooklike(note:IhavenotrestartedmyPostmastersince

thepreviousexample,soIexpectanerrorhere):

$chmoda+xclient2a.py

$./client2a.py

Traceback(innermostlast):

File"./client2a.py",line10,in?

password="cows")



File"/usr/lib/python1.5/site-packages/pgdb.py",line376,in



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Chapter 17.  Using PostgreSQL with Python

Tải bản đầy đủ ngay(0 tr)

×