Com fer servir PostgreSQL amb Python. Mòdul Psycopg2

Per a desenvolupar aplicacions que facin servir PostgreSQL amb Python, el primer pas és instal·lar algun mòdul que permeti accedir a la base de dades des del llenguatge.

El mòdul més popular per accedir a PostgreSQL amb Python és Psycopg2 (http://initd.org/psycopg/).

Instal·lar aquest mòdul a la una distribució Ubuntu no presenta cap dificultat perquè està disponible al “Centre de Programari de l’Ubuntu”.

També instal·lo la testsuite i l’extensió de debug, tot des del “Centre de Programari de l’Ubuntu”

Un cop instal·lats, ja es pot treballar. El primer  pas és revisar la documentació i els exemples. La documentació en línia la podem trobar a http://initd.org/psycopg/docs/. I ha un altre enllaç molt interessant a la wiki de PostgreSQL: http://wiki.postgresql.org/wiki/Using_psycopg2_with_PostgreSQL.

Encara millor: podem utilitzar la documentació local de Python. si a la consola fem pydoc -g, se’ns obrirà   aquesta petita aplicació, que és un mini servidor web de les pàgines HTML de l’ajuda de Python i els seus mòduls:

A més, compta amb un cercador molt senzill amb el que podrem consultar sobre el mòdul que acabem d’instal·lar, el psycopg2. Fent click als tòpics trobats

Ens obrirà un navegador amb la pàgina desitjada.

Doncs bé, un cop vist això, el que faré serà un experiment molt senzill que consistirà en connectar-se a una base de dades existent i executar-hi consultes.

Primer de tot, amb l’Anjuta, creo un projecte nou del tipus Python generic. Per a fer les coses més fàcils, copio l’script de prova disponible

#!/usr/bin/python
# coding: latin-1
#
import psycopg2
import sys


def main():
#Defineix la cadena de connexió
conn_string = “host=’localhost’ dbname=’proves’ user=’postgres’ password=’postgres'”
# la mostra
print “Connectant a la base de dades\n ->%s” % (conn_string)
try:
# obté una connexió, si no es pot connectar, llença una excepció
conn = psycopg2.connect(conn_string)

# conn.cursor retorna un objecte cursor, per a fer les consultes.
cursor = conn.cursor()

print “Connectat!\n”
except:
# obté informació de l’excepció
exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
# mostra la informació i acaba.
sys.exit(“Database connection failed!\n ->%s” % (exceptionValue))


# final
if __name__ == “__main__”:
sys.exit(main()) 

Des del mateix Anjuta puc provar:

EXECUTING:
/media/DISC57GB/wk-python/ProvaPG/src/prova_pg.py 
———————————————-
Connectant a la base de dades
->host=’localhost’ dbname=’proves’ user=’postgres’ password=’postgres’
Connectat!




———————————————-
Program exited successfully with errcode (0)
Press the Enter key to close this terminal … 

Net i a la primera. Ara faré una consulta, afegeixo

#!/usr/bin/python
# coding: latin-1
#
import psycopg2
import sys


def main():
#Defineix la cadena de connexió
conn_string = “host=’localhost’ dbname=’proves’ user=’postgres’ password=’postgres'”
# la mostra
print “Connectant a la base de dades\n ->%s” % (conn_string)
try:
# obté una connexió, si no es pot connectar, llença una excepció
conn = psycopg2.connect(conn_string)

# conn.cursor retorna un objecte cursor, per a fer les consultes.
cursor = conn.cursor()

print “Connectat!\n”

# executa una consulta
cursor.execute(“SELECT * FROM taula1”)


# recupera files de la taula
v_files = cursor.fetchall()

print “Retorna: ” + str(cursor.rowcount) + ” files”


# mostra les files 
for v_fila in v_files:
print str(v_fila[0]) + ” ; ” + v_fila[1] + ” ; ” + v_fila[2]

# i surt
conn.close()
except:
# obté informació de l’excepció
exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
# mostra la informació i acaba.
sys.exit(“Database connection failed!\n ->%s” % (exceptionValue))


# final
if __name__ == “__main__”:
sys.exit(main())

I el resultat, com calia esperar:

EXECUTING:
/media/DISC57GB/wk-python/ProvaPG/src/prova_pg.py 
———————————————-
Connectant a la base de dades
->host=’localhost’ dbname=’proves’ user=’postgres’ password=’postgres’
Connectat!


Retorna: 5 files
1 ; valor 1 ; traducció 1
2 ; valor 2 ; traducció 2
3 ; valor 3 ; traducció 3
4 ; valor 4 ; traducció 4
5 ; valor 5 ; traducció 5


———————————————-
Program exited successfully with errcode (0)
Press the Enter key to close this terminal …

Un senzill experiment de com utilitzar PostgreSQL amb scripts de Python fent servir el mòdul Psycopg2.

Anuncis

Stored Procedures amb PostgreSQL

A l’hora de desenvolupar aplicacions web, una aproximació possible és la de mantenir la lògica de negoci implementada al servidor de base de dades en forma de procediments emmagatzemats, o stored procedures, o dit d’una altre forma:  hi ha vida més enllà d’Hibernate.
La utilització de procediments emmagatzemats pot aportar beneficis evidents: per exemple, ens podem estalviar un munt de transport d’informació entre el servidor de base de dades i el servidor d’aplicacions. També té problemes. Potser el més evident és que la base de dades es carrega amb el cost de processar la lògica, ara bé, per a una quantitat molt gran de processos de negoci, no hi han grans càlculs a realitzar i el cost es redueix, precisament a moure dades entre taules i càlculs simples.
En tot cas, és una opció a tenir en compte.
Els servidors de bases de dades MySQL, PostgreSQL o FireBird, potser els  més populars a Linux, permeten implementar  procediments emmagatzemats.
En aquest post faré un exercici senzill amb procediments emmagatzemats a PostgreSQL.
El cas de PostgreSQL és una mica especial: El llenguatge de procediments, el PL/PGSQL, no està disponible d’entrada. Cal “Crear-lo”. O bé amb una instrucció CREATE LANGUAGE, o bé amb la utilitat createlang. Aquesta és l’opció que he triat.
albert@atenea:~$ createlang –dbname=proves –host=localhost –username=postgres –password PLPGSQL
Password: elmeupassword
La instrucció anterior “activa” el PL/PGSQL a la base de dades ‘proves’ que tinc al meu localhost. l’opció –password força que es demani el password de l’usuari.
Aleshores faig servir el pgAdmin III com a entorn d’administració  i obro una finestra de SQL
 Ala finestra hi escric una funció simple que suma dos números
— Function: provasuma(integer, integer)
— DROP FUNCTION provasuma(integer, integer);
CREATE OR REPLACE FUNCTION provasuma(val1 integer, val2 integer)
  RETURNS integer AS
$$
BEGIN
    /*
    Això és un comentari de més d’una línia
    */
    RAISE NOTICE ‘suma %  i  %’, Val1, Val2;
    RETURN Val1 + Val2;
END; 
$$
LANGUAGE ‘plpgsql’
Coses interessants:
Només podem crear funcions.
Comentaris d’una línia amb —
Comentaris de més d’una línia amb /* … */
El cos de la funció queda determinat per les marques $$
La depuració és un punt fluix i, en principi, fent servir el pgAdmin, o el psql, no ens en queda altre que depurar al vell estil amb printf, en aquest cas amb raise.
La sintaxi és molt similar a la de PL/SQL.
Cal indicar el llenguatge. Per defecte, PostgreSQL admet també les opcions plpgsql, internal,  C i SQL per al llenguatges. Ara bé, “internal” només serveix per a fer alies nous de les funcions ja disponibles, “C” és per enllaçar dinàmicament llibreries de funcions escrites i compilades en aquest llenguatge, “SQL” sí que permet fer funcions però només d’instruccions SQL separades per “;”, finalment, “plpgsql” ens permet fer funcions amb estructures de control, llaços, iteracions…
Com a mostra, la senzilla funció que he escrit abans , també l’hauria pogut escriure com una funció del tipus “SQL”:
— Function: provasuma2(integer, integer)
— DROP FUNCTION provasuma2(integer, integer);
CREATE OR REPLACE FUNCTION provasuma2(integer, integer)
  RETURNS integer ASemès per  ‘select $1 + $2’
  LANGUAGE ‘SQL’
Les funcions  anteriors les puc invocar des de psql o pgAdmin
proves=# select provasuma(23,546);
NOTICE:  suma 23  i  546
 provasuma 
———–
       569
(1 row)
O la segona d’elles:
proves=# select provasuma2(23,546);
 provasuma2 
————
        569
(1 row)
on no apareix el missatge del RAISE.
Finalment, el llenguatge es descriu en aquest enllaç. El més destacable és que, sintàcticament, el PL/pgSQL i el PL/SQL d’Oracle són força similars, de forma que els programadors d’aquest  llenguatge del gegant de les bases de dades en tindran molt de guanyat. Més encara quan el PL/pgSQL vindria a ser un subconjunt del PL/SQL.
Per tal de facilitar la migració de codi de PL/SQL d’Oracle a PL/pgSQL de PostgreSQL en aquest altre enllaç trobem diferències entre tots dos i consells per a la  migració.

OpenOffice.org i PostgreSQL / 31 juliol 2010

OpenOffice.org i PostgreSQL

Hi han diverses alternatives per atacar amb OpenOffice una base de dades PostgreSQL. Potser les més evidents son 1. Utilitzar SDBC, els drivers nadius d’OpenOffice; 2. utilitzar JDBC

1. El Driver SDBC per accedir a PostgresSQL des de l’OpenOffice. Es pot descarregar des del Centre de Programari de l’Ubuntu, o des de http://dba.openoffice.org/drivers/postgresql/postgresql-sdbc-0.7.6a.zip. Aquesta és la versió que cal per a la versió d’OpenOffice 3.2

2. Driver JDBC per a PostgreSQL. Des del Centre de Programari de L’Ubuntu. Els jar queden ubicats a /usr/share/java.
Aquesta ubicació és el lloc escaient per a deixar les llibreries java per aplicacions “de sistema”. Per exemple, aquí es troba el driver d’HyperSonic DB que fa servir OpenOffice Base.

He instal·lat el driver SDBC des del Centre de Programari. En arrencar l’OpenOffice Base i anar a “Connectar amb una base de dades existent” m’ha aparegut el tipus “Postgres”, Bé!

L’he triat. Em demana la URL. Hi poso el següent:
host=localhost port=5432 dbname=proves

El format de la cadena és nom1=valor1 nom2=valor2…  amb les parelles nom=valor separades per espais i sense cometes envoltant al “valor”. Ho remarco perquè el format no té res a veure amb el típic de les connexions JDBC a les que estic més acostumat.

Indico login i password i, sense fer res més, funciona i em connecto a la BD. Puc accedir a les taules de la BD proves i a les taules de l’esquema public. El login i lo password també es poden posar a la cadena. En el meu cas quedaria així:

host=localhost port=5432 user=postgres password=masterkey dbname=proves

Però, pel que es veu, l’OpenOffice3.2 ignora que ja disposa del password i me’l torna  demanar. És un bug? de fet, no m’està malament que me’l demani.

Com accedir a PostgreSQL (o MySQL, o FireBird) amb Lazarus / 31 juliol 2010

Com accedir a PostgreSQL (o MySQL, o FireBird) amb Lazarus

Tanco la serie de “com accedir a una base de dades del tipus xxxx amb Lazarus” amb el post d’avui, en el que desenvolupo una aplicació que accedeix a una taula d’una base de dades del tipus PostgreSQL.

L’entorn és Ubuntu Lucid Lynx 10.04. Amb el Centre de Programari de l’Ubuntu m’he instal·lat  PostgreSQL 8.4 i PgAdmin III. Que pel poc que he vist, és una molt bona eina d’administració i de consulta i força intuitiva.

El primer pas ha estat canviar el password de l’usuari postgres. Per això he fet des d’un terminal

sudo -u postgres psql postgres

i, a continuació, dins de la consola de sql

\password postgres

La barra de l’inici és important. Li indico el nou password: per exemple, “masterkey”. (consulteu l’ajuda al setup de PostgreSQl a Ubuntu).

Un cop fet  això, amb pgAdmin ja podré registrar el servidor Localhost i crear-hi una nova base de dades que anomenaré ‘proves’. A proves, dins l’esquema public, hi creo una taula taula1, amb les mateixes columnes que en posts anteriors:  id (numèrica i PK), valor (text) i traducció (text).

Puc fer servir pgAdmin per a informar amb dades la taula.

I ara creo l’aplicació amb Lazarus. Idèntica a la del post  accedir amb Lazarus a SQLite. Amb un parell de diferències. En aquesta ocasió, els components d’accés seran uns altres:

Poso un component de Connexió a Postgres del tipus TPQConnection (objecte PQConnection1)
Un objecte TSQLTransaction (SQLTranasaction1) i un TSQLQuery (SQLQuery1) i els connecto entre ells.
En particular:
PQConnection1. UserName: postgres
PQConnection1.password: masterkey
PQConnection1.hostname: localhost
PQConnection1.databasename: proves
PQConnection1.transaction: SQLTransaction1

SQLTransaction1. Database: PQConnection1

SQLQuery1.database: PQConnection1
SQLQuery1.transaction: SQLTransaction1
SQLQuery1.SQL: select id,valor,traduccio from taula

La resta és un camp memo i tres botons Carregar (Button1Click), Netejar (Button2Click) i Sortir (Button3Click).

El codi del form és:

unit unProvaPostgres01;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, pqconnection, sqldb, FileUtil, LResources, Forms, Controls,
  Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Memo1: TMemo;
    PQConnection1: TPQConnection;
    SQLQuery1: TSQLQuery;
    SQLTransaction1: TSQLTransaction;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  sId, sValor, sTraduccio, sLinea: String;
begin
  (* obre connexions a la BD *)
  PQConnection1.Open;
  SQLQuery1.Open;

  (* itera a través de la BD *)
  SQLQuery1.First;
  while not SQLQuery1.EOF do begin
    sId := SQLQuery1.FieldByName(‘id’).AsString;
    sValor := SQLQuery1.FieldByName(‘valor’).AsString;
    sTraduccio := SQLQuery1.FieldByName(‘traduccio’).AsString;
    sLinea := sId + ‘; ‘ + sValor + ‘; ‘ + sTraduccio;
    Memo1.Append(sLinea);
    SQLQuery1.Next;
  end;

  // tanca la query
  SQLQuery1.Close;
  PQConnection1.Close;

end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Memo1.Clear;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  Application.Terminate;
end;

initialization
  {$I unprovapostgres01.lrs}
end.
EL codi anterior funciona exactament igual amb bases de dades del tipus FireBird / InterBase, o amb Bases de dades del tipus MySQL (si més no, fins a la 5.0), només que canviant el component TPQConnection per un TIBConnection per a les FireBird/InterBase, o per un TMySQL40Connection per a les MySQL4.0, TMySQL41Connection per a MySQL4.1 o TMySQL50Connection per a les MySQL50.

Amb les bases de dades del tipus MySQL 5.1 el control de connexió disponible amb Lazarus SqlDB funciona a mitges. No tanca bé. Suposo que es podria buscar algun control alternatiu, però cal trobar-lo. És una mala notícia perquè la versió de MySQL del repositori de programari d’Ubuntu per a Lucid és la 5.1

En tot cas, aquest és el HelloWorld de la connexió de Lazarus a Postgres (i a FireBird i fins a les MySQL 5.0).