Programacion en python_3
Upcoming SlideShare
Loading in...5
×
 

Programacion en python_3

on

  • 1,331 views

 

Statistics

Views

Total Views
1,331
Views on SlideShare
1,318
Embed Views
13

Actions

Likes
0
Downloads
24
Comments
0

2 Embeds 13

http://wozgeass.wordpress.com 12
http://www.slideshare.net 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Programacion en python_3 Programacion en python_3 Presentation Transcript

  • Programación en Python Parte 3: Persistencia y BB.DD. Mariano Reingart reingart@gmail.com
  • Persistencia y serialización: pickle Pickle: convertir objeto python en secuencia de bytes Funciones de pickle: dumps(objeto, proto): serializa a un string dump(objeto, archivo, proto): guarda en archivo loads(cadena, proto): des-serializa un string load(archivo, proto): carga desde archivo >>> import pickle >>> s = pickle.dumps({1:'a',2:'b'},0) >>> s "(dp0nI1nS'a'np1nsI2nS'b'np2ns." >>> print pickle.loads(s) {1: 'a', 2: 'b'}
  • Persistencia y serialización: pickle import pickle data1 = {'a': [1, 2.0, 3, 4+6j], 'b': ('string', u'Unicode'),'c': None} selfref_list = [1, 2, 3] selfref_list.append(selfref_list) output = open('data.pkl', 'wb') pickle.dump(data1, output) # Serializar un dict pickle.dump(selfref_list, output, -1) # Serializar list output.close() pkl_file = open('data.pkl', 'rb') data1 = pickle.load(pkl_file) # Deserializar el dict pprint.pprint(data1) data2 = pickle.load(pkl_file) # Deserializar la lista pprint. pprint(data2) pkl_file.close()
  • Persistencia y serialización: shelve Shelve: objeto similar a un diccionario persistente open(filename, flag='c', protocol=None, writeback=False): crea un diccionario persistente flag= 'r': solo lectura, 'w': lectura/escritura, 'c': creación y lectura/escritura, 'n': nuevo Shelve.sync(): sincronizar (writeback=True) Shelve.close(): grabar y cerrar diccionario >>>import shelve >>> d = shelve.open(filename) # abrir archivo >>> d['clave'] = 'datos' # almacenar datos en una clave >>> data = d['clave'] # leer una COPIA de los datos >>> del d ['clave'] # borra los datos almacenados
  • Ejemplo práctico: universidad.py Enunciado: administrar las cursadas y calificaciones de los alumnos de una universidad "simplificada". Profesores (dni, nombre, apellido, legajo) Materias (código, nombre) Cursos (materia, año, profesor) Exámenes (materia, nota, fecha) Alumnos (dni, nombre, apellido, nro_matrícula, cursos, exámenes) Universidad (alumnos, profesores, plan_estudio)
  • Ejemplo práctico: universidad.py Diagrama de clases:
  • Ejemplo práctico: universidad.py class Persona: "Clase que representa una persona" def __init__(self, dni, nombre, apellido): "Constructor del objeto" self.dni = dni self.nombre = nombre self.apellido = apellido def __str__(self): "Devuelvo la representación como string" return "%s, %s" % (self.nombre, self.apellido) def __repr__(self): "Devuelve la representación interna" return "Persona(dni=%s, nombre=%s, apellido=%s)" % ( repr(self.dni), repr(self.nombre),...) def __hash__(self): "Devuelvo el identificador único del objeto" return self.dni
  • Ejemplo práctico: universidad.py class Profesor(Persona): def __init__(self, dni, nombre, apellido, legajo): Persona.__init__(self, dni, nombre, apellido) self.legajo = legajo
  • Ejemplo práctico: universidad.py class Materia: "Clase para representar una materia" def __init__(self, codigo, nombre): self.codigo = codigo self.nombre = nombre def __str__(self): return "%s (%s)" % (self.nombre, self.codigo) def __repr__(self): return "Materia(codigo=%s, nombre=%s)" % ( repr(self.codigo), repr(self.nombre)) def __hash__(self): return self.codigo
  • Ejemplo práctico: universidad.py class Curso: def __init__(self, materia, anio, profesor, cupo=30): self.materia = materia self.anio = anio self.profesor = profesor self.cupo = cupo self.alumnos = [] def inscribir(self, alumno): if self.cupo<len(self.alumnos): raise RuntimeError("No hay mas lugar!") self.alumnos.append(alumno) alumno.inscribir(curso=self) def __repr__(self): return "Curso(materia=%s, profesor=%s)" % ( repr(self.materia), repr(self.profesor))
  • Ejemplo práctico: universidad.py class Examen: def __init__(self, materia, nota, fecha): self.materia = materia self.nota = nota self.fecha = fecha @property def aprobado(self): return self.nota >= 4 def __repr__(self): return "Examen(materia=%s, nota=%s, fecha=%s)" % (repr(self.materia), repr(self.nota), repr(self.fecha))
  • Ejemplo práctico: universidad.py class Alumno(Persona): "Clase para representar un Alumno" def __init__(self, dni, nombre, apellido, nro_matricula): Persona.__init__(self, dni, nombre, apellido) self.nro_matricula = nro_matricula self.cursos = [] # lista de materias cursadas self.examenes = [] # lista de exámenes rendidos def inscribir(self, curso): self.cursos.append(curso) def rendir(self, materia, nota, fecha): examen = Examen(materia, nota, fecha) # agrego el examen a la lista de los exámenes self.examenes.append(examen)
  • Ejemplo práctico: universidad.py class AlumnoRegular(Alumno): def rendir(self, materia, nota, fecha): if self.buscar_cursadas(materia): Alumno.rendir(self, materia, nota, fecha) else: raise RuntimeError("El alumno no curso la materia %s" % materia) class AlumnoLibre(Alumno): "Los alumnos libres no necesitan inscribirse previamente" pass
  • Ejemplo práctico: universidad.py class Universidad: def __init__(self): self.alumnos = [] self.profesores = [] self.plan_estudio = [] self.cursos = [] def guardar(self, nombre_archivo="universidad.dat"): "Grabo la instancia en un archivo" archivo = open(nombre_archivo, "wb") # serializo el objeto universidad (max.protocolo) pickle.dump(universidad, archivo, -1) @staticmethod def cargar(nombre_archivo="universidad.dat"): "Cargg la instancia desde un archivo" archivo = open(nombre_archivo, "rb") return pickle.load(archivo)
  • Ejemplo práctico: universidad.py def analitico(self, alumno): "Muestro el estado de las materias del alumno" print "Notas para el alumno: %s" % alumno for materia in self.plan_estudio: cursada = alumno.buscar_cursadas(materia) and True or False # obtengo el último exámen rendido examenes = alumno.buscar_examenes(materia) if examenes: # extraigo la última nota y fecha de exámen nota = examenes[-1].nota fecha = examenes[-1].fecha else: nota = fecha = '' print "%3s: %-20s %5s %10s %s" % ( materia.codigo, materia.nombre, nota, fecha, cursada and 'Cursada' or '') print
  • Ejemplo práctico: universidad.py def recibido(self, alumno): "Reviso que todas las materias del plan de estudio esten aprobadas" for materia in self.plan_estudio: # busco los examenes aprobados de esta materia if not [examen for examen in alumno.buscar_examenes(materia) if examen.aprobado]: raise RuntimeError("%s no aprobo %s" % (alumno, materia)) #return False # no aprobó ningún/no tiene exámen return True # aprobó todas las meterias
  • Ejemplo práctico: universidad.py if __name__ == "__main__": # si existen los datos, los deserealizo if os.path.exists("universidad.dat"): universidad = Universidad.cargar() print "Cursos:" pprint.pprint(universidad.cursos) print "Alumnos" pprint.pprint(universidad.alumnos) else: universidad = Universidad() alumno1 = AlumnoLibre(dni=1234, nombre="Juan", apellido="Perez", nro_matricula=1234) alumno2 = AlumnoRegular(dni=5678, nombre="Luis", apellido="Gonzales", nro_matricula=1234) universidad.alumnos.extend([alumno1, alumno2]) ... universidad.guardar()
  • Ejemplo práctico: universidad.py >>> ================================ RESTART >>> Notas para el alumno: Juan, Perez 1: Bases de datos 5 2009-01-03 Cursada 2: Programacion I 3 2009-02-03 Cursada 3: Programacion II 7 2009-02-03 Notas para el alumno: Luis, Gonzales 1: Bases de datos 7 2009-01-03 Cursada 2: Programacion I 3: Programacion II 10 2009-02-03 Cursada Juan, Perez Juan, Perez no aprobo Programacion I (2) Luis, Gonzales Luis, Gonzales no aprobo Programacion I (2) >>> alumno1.rendir(materia2, nota=4, fecha=datetime.date.today()) >>> universidad.guardar()
  • Ejemplo práctico: universidad.py >>> ================================ RESTART >>> alumno1 Traceback (most recent call last): File "<pyshell#9>", line 1, in <module> alumno1 NameError: name 'alumno1' is not defined >>> alumno1=universidad.alumnos[0] >>> universidad.recibido(alumno1) True >>> universidad.analitico(alumno1) Notas para el alumno: Juan, Perez 1: Bases de datos 5 2009-01-03 Cursada 2: Programacion I 4 2009-08-20 Cursada 3: Programacion II 7 2009-02-03 >>>
  • Ejemplo práctico: universidad.py >>> ================================ RESTART >>> Notas para el alumno: Juan, Perez 1: Bases de datos 5 2009-01-03 Cursada 2: Programacion I 3 2009-02-03 Cursada 3: Programacion II 7 2009-02-03 Notas para el alumno: Luis, Gonzales 1: Bases de datos 7 2009-01-03 Cursada 2: Programacion I 3: Programacion II 10 2009-02-03 Cursada Juan, Perez Juan, Perez no aprobo Programacion I (2) Luis, Gonzales Luis, Gonzales no aprobo Programacion I (2) >>> alumno1.rendir(materia2, nota=4, fecha=datetime.date.today()) >>> universidad.guardar()
  • DB-API: Interfase Estándar de BB.DD. Funciones y atributos del Módulo: connect(parametros...): crea una conexión paramstyle: formato de los parámetros 'qmark': ej. '...WHERE name=?' 'numeric': ej. '...WHERE name=:1' 'named': ej. '...WHERE name=:name' 'format': ej. '...WHERE name=%s' 'pyformat': ej. '...WHERE name=%(name)s' Excepciones Tipos de datos avanzados
  • DB-API: Interfase Estándar de BB.DD. Funciones y atributos del Módulo: Excepciones Warning: advertencia (ej. texto truncado) Error: clase base de errores InterfaseError: error con la comunicación DatabaseError: error con la base en si OperationalError: error en "inesperado" IntegrityError: integridad (PK, FK, etc.) InternalError: error interno de la base de datos ProgrammingError: error en el SQL NotSupportedError: funcionalidad no soportada
  • DB-API: Interfase Estándar de BB.DD. Funciones y atributos del Módulo: Tipos/constructores Date(año,mes,día): fecha Time(hora,minuto,segundo): hora Timestamp(año,mes,día,hora,minuto, segundo): fecha y hora Binarycasdena): objetos grandes (blobs) STRING: tipo para cadenas BINARY: tipo para blobls NUMBER: numeros DATETIME: fechas y/o horas ROWID: identificador de filas
  • DB-API: Interfase Estándar de BB.DD. Objetos Conexión: .close(): cierra la conexión (.rollback si hay datos pendientes) .commit(): confirma transacción pendiente .rollback(): deshace una transacción pendiente .cursor(): crea un objeto Cursor
  • DB-API: Interfase Estándar de BB.DD. Objetos Cursor: .execute(sql, params): ejecuta una consulta sql aplicando los parámetros params .description: secuencia de datos de los campos: (name, type_code, display_size, internal_size, precision, scale, null_ok) .rowcount: cantidad de filas devueltas o afectadas .fechone(): devuelve un registro .fechall(): devuelve todos los registros .close(): cierra la conexión
  • DB-API: Interfase Estándar de BB.DD. Pasos: 1. Importar el conector 2. Conectarse a la base de datos (función connect del módulo conector) 3. Abrir un Cursor (método cursor de la conexión) 4. Ejecutar una consulta (método execute del cursor) 5. Obtener los datos (método fetch o iterar sobre el cursor) 6. Cerrar el cursor (método close del cursor)
  • DB-API: Ejemplo SqLite import sqlite3 con = sqlite3.connect(":memory:") cur = con.cursor() cur.execute(""" CREATE TABLE persona (nombre, apellido, edad) """) con.commit() cur.execute(""" INSERT INTO persona VALUES ('Juan', 'Perez', 25); """) cur.execute(""" INSERT INTO persona VALUES ('Nilda', 'Rodriguez', 25); """) con.commit() cur.execute("SELECT nombre, apellido, edad FROM persona") for nombre, apellido, edad in cur: print nombre, apellido, edad
  • DB-API: Ejemplo SqLite import sqlite3 con = sqlite3.connect("mydb") # acceder por nombre a las filas del cursor: con.row_factory = sqlite3.Row cur = con.cursor() cur.execute("select apellido, edad from persona") for row in cur: assert row[0] == row["apellido"] assert row["apellido"] == row["aPeLLido"] assert row[1] == row["edad"] assert row[1] == row["EdaD"]
  • DB-API: Ejemplo SqLite import sqlite3 con = sqlite3.connect(":memory:") con.execute("create table persona (id integer primary key, nombre varchar unique)") # con.commit() se llama automáticamente si ok (con with) with con: con.execute("insert into persona(nombre) values (?)", ("Juan",)) # con.rollback() se llama si hay excepción: try: with con: con.execute("insert into persona(firstname) values (?)", ("Juan",)) except sqlite3.IntegrityError: print "no se puede agregar Juan dos veces"
  • DB-API: Ejemplo MySql >>> import MySQLdb >>> db = MySQLdb.connect(host="localhost", user="root", ... passwd="mypassword", db="PythonU") >>> cursor = db.cursor() cursor.execute("SELECT * FROM Students") >>> cursor.fetchone() (1L, 'Joe', 'Campbell', datetime.date(2006, 2, 10), 'N') >>> cursor.fetchall() ((1L, 'Joe', 'Campbell', datetime.date(2006, 2, 10), 'N'), (2L, 'Joe', 'Doe', datetime.date(2004, 2, 16), 'N'), (3L, 'Rick', 'Hunter', datetime.date(2005, 3, 20), 'N'), (4L, 'Laura', 'Ingalls', datetime.date(2001, 3, 15), 'Y'), (5L, 'Virginia', 'Gonzalez', datetime.date(2003, 4, 2), 'N'))
  • DB-API: Ejemplo PostgreSQL >>> import psycopg2 >>> conn = psycopg2.connect(database='test', user='postgres', password='pass', host='localhost') >>> # Crear un cursor para obtener y ejecutar consulta: >>> cur = conn.cursor() >>> cur.execute("SELECT * FROM estudiante") >>> rows=cur.fetchall() >>> print rows [['Joe', 'Capbell', datetime.date(2006, 2, 10), False, 1], ['Joe', 'Doe', datetime.date (2004, 2, 16), False, 2], ['Rick', 'Hunter', datetime.date(2005, 3, 20), False, 3], ['Laura', 'Ingalls', datetime.date(2001, 3, 15), True, 4], ['Virginia', 'Gonzalez', datetime.date(2003, 4, 2), False, 5]]
  • DB-API: Ejemplo PostgreSQL >>> import psycopg2.extras >>> cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor) >>> cur.execute("SELECT * FROM estudiante") >>> for row in cur: # itero sober cada fila >>> # row es un diccionario, con las claves = campos >>> print "Nombre y Apellido: %s, %s " % (row['nombre'],row['apellido']) Nombre y Apellido: Joe, Capbell Nombre y Apellido: Joe, Doe Nombre y Apellido: Rick, Hunter Nombre y Apellido: Laura, Ingalls Nombre y Apellido: Virginia, Gonzalez >>> print cur.description (('nombre', 1043, 8, -1, None, None, None), ('apellido', 1043, 8, -1, None, None, None), ('fecha', 1082, 10, 4, None, None, None), ('booleano', 16, 1, 1, None, None, None), ('legajo', 23, 1, 4, None, None, None))
  • DB-API: Ejemplo PostgreSQL >>> #Parámetros: >>> cur = conn.cursor() >>> cur.execute("insert into personas (apellido) values (%s)" , ["D'agostino"]) >>> cur.execute("insert into personas (apellido) values (%(apellido)s)" , {"apellido":"D'agostino"})
  • PlPython: Procedimientos almacenados El lenguaje procedural plpython permite escribir funciones python para la base de datos relacional PostgreSQL. El cuerpo de una funcion plpythonu es simplemente un script de Python. Los argumentos son pasados como elementos de una lista args; los argumentos por nombre son pasados como variables ordinarias. El resultado es devuelto con un return o un yield Los valores NULL equivalen a None. Diccionario SD y GD (global)
  • PlPython: Procedimientos almacenados Ejemplo Simple: >>> CREATE FUNCTION pymax (a integer, b integer) RETURNS integer AS $$ if (a is None) or (b is None): return None if a > b: return a return b $$ LANGUAGE plpythonu; -- invoco la función: SELECT pymax(2, 3); -- devuelve 3
  • PlPython: Procedimientos almacenados Recibir tipos compuestos: CREATE TABLE empleado ( nombre TEXT, salario INTEGER, edad INTEGER ); CREATE FUNCTION sueldo_alto (e empleado) RETURNS boolean AS $$ if e["salario"] > 200000: return True if (e["edad"] < 30) and (e["salario"] > 100000): return True return False $$ LANGUAGE plpythonu;
  • PlPython: Procedimientos almacenados Devolver tipos compuestos: CREATE FUNCTION crear_persona (nombre TEXT, apellido TEXT) RETURNS persona AS $$ return [ nombre, apellido ] # o como tupla: return ( nombre, apellido ) # o como diccionario: return { "nombre": nombre, "apellido": apellido } # return Persona(nombre, apellido) $$ LANGUAGE plpythonu;
  • PlPython: Procedimientos almacenados Devolver multiples tipos escalares o compuestos: CREATE TYPE saludo AS ( mensaje TEXT, -- hola a_quien TEXT -- mundo ); CREATE FUNCTION saludar (mensaje TEXT) RETURNS SETOF saludo AS $$ # devolver una tupla conteniendo lista de tipos # todas las otras combinaciones son posibles return ( [ mensaje, "Mundo" ], [ mensaje, "PostgreSQL" ], [ mensaje, "PL/Python" ] ) ##for a_quien in [ "Mundo","PostgreSQL","PL/Python"]: ## yield ( mensaje, a_quien ) $$ LANGUAGE plpythonu;
  • PlPython: Procedimientos almacenados Disparadores (triggers), recibe diccionario TD: TD["new"]: valores nuevos de la fila afectada TD["old"]: valores viejos de la fila afectada TD["event"]: tipo de evento "INSERT", "UPDATE", "DELETE", o "UNKNOWN" TD["when"]: momento en que se ejecutó: "BEFORE" (antes del commit), "AFTER" (despues del commit), o "UNKNOWN" TD["args"]: argumentos adicionales Si TD["when"] es BEFORE: se puede devolver None or "OK", "SKIP o "MODIFY"
  • PlPython: Procedimientos almacenados Acceso a la base de datos: módulo plpy plpy.error y plpy.fatal disparan una excepción python, si no se controla, se propaga y causa que la transacción se aborte. Equivalente a llamar raise plpy.ERROR(msg) y raise plpy.FATAL(msg) plpy.debug(msg), plpy.log(msg), plpy.info(msg), plpy.notice(msg), plpy.warning(msg) informan mensajes de distinta prioridad plpy.execute(sql, limite): ejecutar consultas plpy.prepare(sql, [tipos]): preparar consultas
  • PlPython: Procedimientos almacenados Ejecutar consulta con execute: se obtienen las filas recorriendo el resultado por numero de fila y nombre de columna nrows: devuelve cantidad de filas status: estado interno rv = plpy.execute("SELECT * FROM mi_tabla", 5) for fila in rv: print fila['columna']
  • PlPython: Procedimientos almacenados Preparar y ejecutar consulta con execute: # preparo el plan plan = plpy.prepare("SELECT apellido FROM usuario WHERE nombre = $1 AND casado = $2 ", [ "text", "boolean" ]) # ejecuto el plan con los parámetros rv = plpy.execute(plan, [ "Mariano", True ], 5) CREATE FUNCTION usar_plan() RETURNS trigger AS $$ if SD.has_key("plan"): plan = SD["plan"] # está el plan, lo reutilizo else: # no esta el plan, lo creo y almaceno plan = plpy.prepare("SELECT 1") SD["plan"] = plan # continua la función... $$ LANGUAGE plpythonu;
  • PlPython: Procedimientos almacenados Preparar y ejecutar consulta con execute: # preparo el plan plan = plpy.prepare("SELECT apellido FROM usuario WHERE nombre = $1 AND casado = $2 ", [ "text", "boolean" ]) # ejecuto el plan con los parámetros rv = plpy.execute(plan, [ "Mariano", True ], 5) CREATE FUNCTION usar_plan() RETURNS trigger AS $$ if SD.has_key("plan"): plan = SD["plan"] # está el plan, lo reutilizo else: # no esta el plan, lo creo y almaceno plan = plpy.prepare("SELECT 1") SD["plan"] = plan # continua la función... $$ LANGUAGE plpythonu;
  • PlPython: Procedimientos almacenados Ejemplo: analizador de direcciones CREATE TYPE direccion AS ( calle1 TEXT, calle2 TEXT, altura INTEGER ); CREATE OR REPLACE FUNCTION analizar_dir(dir text) RETURNS direccion AS $BODY$ def is_numeric(x): return not [y for y in x if not '0'<=x<='9'] ... return nombres[0], nombres[1], altura and int(altura[-6:]) or None $BODY$ LANGUAGE 'plpythonu' IMMUTABLE; select calle1, calle2, altura from analizar_dir('balcarce 50 esquina rivadavia')
  • Documentación y Ayuda Documentación Oficial: http://docs.python.org/ Libro Python para todos Python Argentina: Aprendiendo Python