Herramientas de usuario

Herramientas del sitio


script:python:xtra

¡Esta es una revisión vieja del documento!


Xtra (Python)

Tips

  • Ocultar funciones y usar variables creadas temporalmente:
def foo():
	def bar():
		x = 5 # x is now in scope
		return x + y # y is defined in the enclosing scope later
	y = 10
	return bar() # now that y is defined, bar's scope includes y
  • Creación de propiedad fuera de clase:
>>> Foo.y = 10
>>> g = Foo()
>>> g.y
10
  • setattr
class C(object):
        def __setattr__(self, name, value):
            if hasattr(self, name):
                raise AttributeError, "attributes are write-once"
            object.__setattr__(self, name, value)
  • Ejecutar un fichero python: execfile( fichero )
  • Recoger los parámetros al ejecutable: sys.argv
  • Ruta del ejecutable: os.getcwd() ← Si pides los parámetros del ejecutable, el primero es el nombre del archivo, la ruta del ejecutable sólo es la ruta, sin el nombre del archivo .py. Se podría decir pues que los argumentos son: sys.argv[1:]
  • Saber tamaño fichero: os.path.getsize( fichero )

Recoger el contenido de una web

Para ello usaremos la función urlopen que está en el módulo urllib. Excepto en el constructor, los métodos para usarlos son…

import urllib
f = urlopen(’http://www.google.es)
for linea in f:
    print linea[:-1]
f.close()

Lanzar un ejecutable

import os
args = []
print os.execv(('c:\\calc.exe'), args)

Aunque en Windows me ha funcionado mejor:

import os
def start (program, *args):
   return os.spawnv(os.P_NOWAIT, program, (program,) + args)
start("C:\\Archivos de programa\\Webteh\\BSplayerPro\\bsplayer.exe")

… o …

import subprocess
subprocess.Popen([r'C:\Archivos de programa\Webteh\BSplayerPro\bsplayer.exe',''])

Recoger variables del sistema

Podemos coger datos internos del operativo tales como la carpeta donde se instalan los programamas, la carpeta de los arhcivos temporales… Las variables del sistema vienen en un diccionario al usar: os.environ
Por ejemplo, para recoger el nombre del ordenador:

	os.environ.get('COMPUTERNAME')

Las variables, hay más a parte de estas pero, son: COMPUTERNAME, SCRIPT_NAME (nombre del archivo ejecutado), REMOTE_ADDR (una variable de conexión, para cgis te dice la conexión de la petición)

Ordenar por valores de diccionario

Por ejemplo coger un diccionario con las notas de alumnos y ordenarlos por nota:

	>>> def informe (tarifas) :
		estudiantes = tarifas.keys()
		estudiantes.sort()
		for estudiante in estudiantes :
			print "%-20s %12.02f" % (estudiante, tarifas[estudiante])
 
 
	>>> tarifas = {'mariaa': 6.23, 'jossie': 5.45, 'jesus': 4.25}
	>>> informe(tarifas)
	jesus                        4.25
	jossie                       5.45
	mariaa                       6.20

Serie de Fibonacci

>>> a,b = 0,1
>>> while b < 100:
	a,b = b,(a+b)
	print b,

Excepciones

try:
    raise Exception()
except:
    print "Sorry:", sys.exc_type + ":", sys.exc_value
 
try:
    raise Exception("Fallo!")
except:
    print sys.exc_value
 
try:
    import Image
except ImportError, exc:
    raise SystemExit("PIL must be loaded to run this example")

Diccionarios

  • Crear mediante dos listas:
>>> seq1 = ('a','b','c','d')
>>> seq2 = [1,2,3,4]
>>> d = dict(zip(seq1,seq2))
>>> d
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
  • Combinar:
>>> d = {'apples': 1, 'oranges': 3, 'pears': 2}
>>> ud = {'pears': 4, 'grapes': 5, 'lemons': 6}
>>> d.update(ud)
>>> d
{'grapes': 5, 'pears': 4, 'lemons': 6, 'apples': 1, 'oranges': 3}

Trato de cadenas

  • join \ split:
>>> s = "this   is\na\ttest"
>>> print s
this   is
a	test
>>> print s.split() 
['this', 'is', 'a', 'test']
>>> print " ".join(s.split())
'this is a test'
  • split sin argumentos divide en espacios en blanco.
  • join agrupa una lista indicando, que el string en que se llama es lo que separará los elementos.
  • Pasar a mayusculas: var.upper()
  • Para mostrar en un string un float con un solo decimal:
print "You weigh %.1f stone." % (mass_stone)
  • Para hacer que un string ocupe un lugar concreto:
	>>> s = 'foo'
	>>> s
	'foo'
	>>> s.ljust(7)
	'foo '
	>>> s.rjust(7)
	' foo'
	>>> s.center(7)
	' foo '
  • Parametrizar
for t in (('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
		('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00),
		('2006-04-06', 'SELL', 'IBM', 500, 53.00),
		):
	c.execute('insert into stocks values (?,?,?,?,?)', t)

Decodificando datos binarios

Módulo binascii

Existe el módulo binascii que trae distintas funciones para recoger los datos en un formato u otro:

binascii.b2a_base64(data)
binascii.b2a_hex(data)
binascii.b2a_uu(data)
binascii.crc32(data, 0)
binascii.hexlify(data)

Modulo array

También podemos hacerlo mediante el módulo array, este define un objeto con un tipo concreto (caracteres, integers, floats…) el cual se indica en la creación que es de la siguiente forma:

import array
a = array.array('c', data)

Siendo el primer parámetro pasado (c en este caso) el tipo que es. Los tipos se definen por (c (caracter a partir de un byte), b, B, u, h (short a partir de dos bytes), H, i (integer a partir de dos bytes), I, l (long a partir de cuatro bytes), L, f (float a partir de cuatro bytes), d (doubles a partir de cuatro bytes)).

Modulo struct

Muy útil para la extracción de datos tipados de una cadena en bytes, y viceversa, pasar datos a cadena de bytes.
Para recoger datos utilizamos la función unpack a la cual se le pasa un formato (que se forma a partir de los valores de la siguiente tabla) y la cadena de bytes:

format tipo leido numero de bytes
c char 1
b byte 1
B ubyte 1
h short 2
H ushort 2
i int 4
I uint 4
l long 4
L ulong 4
q long (64b) 8
Q ulong (64b) 8
f float ?
d double 8
s char[] 1
p char[] 1

Con este formato podríamos indicar qué es lo que viene en la cadena de bytes pasada, por ejemplo, cHIII esperaría a leer de los bytes un carácter, un unsigned short y tres unsigned int, es decir, la cadena de bytes debería de tener 11 bytes. El ejemplo también lo podríamos escribir como cH3I, el resultado sería una lista. En el siguiente ejemplo se tiene un array de bytes (data) y se sabe que el primer es un número y el segundo un carácter. Luego también habría otro byte, pero este se imprimiría en la siguiente línea:

print struct.unpack("Bc", data[:2])
print struct.unpack("B", data[2:3])

El primer carácter del formato puede indicar hacia donde se dirigen los bytes, por ejemplo puede ser:

  • !: Como se envia por red.
  • <: Little-endian.
  • >: Big-endian.

Otras funciones útiles podrían ser calcsize que pasándole un formato indica qué tamaño debería de tener este:

>>> struct.calcsize('hhl')
8

O también podemos aprovechar el tipo namedtuple para crear objetos:

>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', data))
Student(name='raymond   ', serialnum=4658, school=264, gradelevel=8)

Y si quisieramos leer de un archivo binario…

>>> import struct
>>> f = file('test.chm','r')
>>> s = f.read(4*1 + 3*4)
>>> struct.unpack("4s3I", s)
('ITSF', 3L, 96L, 1L)

Sockets

Para utilizarlo debemos importar el modulo socket:

import socket

Utilidades

Recoger la ip como número

packed_ip = socket.inet_aton("208.146.240.1")
packed_ip = socket.inet_aton("www.oreilly.com")

Convertir un número en ip

ip_adress = socket.inet_ntoa(packed_ip)

Coger ip\puerto de un socket

socketobj.getsockname()

Uso

  1. Crear un socket con socket.socket.
  2. Si vamos a recibir tendremos que hacer un bind del puerto.

Servidor UDP

import socket
import sys
 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
    s.bind(('', server_port))
except socket.error, err:
    print "Couldn't be a udp server on port %d : %s" % (
            server_port, err)
    raise SystemExit
 
while True:
    datagram = s.recv(MAX_TO_READ)
    if not datagram:
        break
    # do something
s.close()

Simplificación

Creación de un server UDP

import SocketServer
 
PORTNO = 5151
 
class handler(SocketServer.DatagramRequestHandler):
    def handle(self):
        newmsg = self.rfile.readline().rstrip()
        print "Client %s said ``%s''" % (self.client_address[0], newmsg)
        self.wfile.write(self.server.oldmsg)
        self.server.oldmsg = newmsg
 
s = SocketServer.UDPServer(('',PORTNO), handler)
print "Awaiting UDP messages on port %d" % PORTNO
s.oldmsg = "This is the starting message."
s.serve_forever()

Creación de un server HTTP

import sys
import BaseHTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
 
 
HandlerClass = SimpleHTTPRequestHandler
ServerClass  = BaseHTTPServer.HTTPServer
Protocol     = "HTTP/1.0"
 
if sys.argv[1:]:
    port = int(sys.argv[1])
else:
    port = 8000
server_address = ('127.0.0.1', port)
 
HandlerClass.protocol_version = Protocol
httpd = ServerClass(server_address, HandlerClass)
 
sa = httpd.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
httpd.serve_forever()

Formatos de datos

XML

Para trabajar con XML en Python es necesario importar: xml.dom.minidom. Ahora podemos…

  • Coger un archivo .xml: archivo = xml.dom.minidom.parse(“archivo.xml”)
  • Mostrar código del archivo: archivo.toxml()
  • Coger elementos por el nombre: elements = archivo.getElementsByTagName(“name”)
  • Acceder a los nodos de un elemento: nodo = elements.item(0)
  • Saber si un nodo tiene subnodos: nodo.hasChildNodes()
  • Coger los dubnodos subnodos: subnds = nodo.childNodes
  • Saber de un nodo…
    • nombre: nodo.nodeName
    • tipo: nodo.nodeType
    • valor: nodo.nodeValue
  • Coger atributos: attr = nodo.attributes
  • Coger un atributo con el nombre tal: subn = attr.getNamedItem(“tal”)

Si llegas a un nodo que tiene un valor, del estilo <nombre>nom</nombre>, el nodo al que has llegado (nombre) tendrá como nodeName “nombre” pero None como nodeValue, para ello tendrás que coger sus “childNodes”, entonces el primer elemento de los childNodes tendrá el nodeName a None, pero el nodeValue como “nom”.

  • Para más información lee “Python and XML - An introduction.pdf” en la sección de documentos de xml.
  • Existen librerías para el trato avanzado de XML, mira en la sección de librerías.

JSON

A partir de la versión 2.6 de Python podemos utilizar un encoder\decoder de json en Python (http://docs.python.org/library/json.html).

SQLite y Python

Desde la versión 2.5 de Python podemos utilizar el módulo sqlite3 el cual nos permite acceder a una base de datos sqlite3.

Acciones básicas

Conexión

import sqlite3
db = sqlite.connect("c:\\prueba.db")

Ejecución de sql

c = db.cursor()
c.execute("insert into data (id) values (1)")
db.commit()

Ejecución de consulta

c = db.cursor()
c.execute("select * from data")
for row in c:
  print row

Funciones de un cursor

  • fetchall(): Trae todo el resultado en una lista.

Acciones avanzadas

Insertar una fecha

>>> t = time.localtime()
>>> ts = sqlite3.Timestamp(t[0], t[1], t[2], t[3], t[4], t[5]);
>>> c.execute ("insert into fecha (fecha) values (?)", (ts,))

Insertar un blob

query = u'''insert into data VALUES(?, ?)'''
c = db.cursor()
b = sqlite3.Binary(data)
c.execute(query,(id,b))
db.commit()

Programación Win32

API Win32

Una vez instalado el paquete PyWin podremos acceder a la api de Windows mediante el módulo win32gui. Las constantes para este las encontraremos en win32con.

>>> import win32gui as gui
>>> import win32con as con
>>> bsp = gui.FindWindow("BSPlayer", None)
>>> bsp
525126
>>> bsp_cmd = con.WM_USER + 2
>>> gui.SendMessage(bsp, bsp_cmd, 0x10000, 0)

COM

Mediante Python podemos acceder a objetos COM, esto nos permite desarrollar para programas (ya sean tareas automatizadas, plugins, scripts…). Para ello al instalar Python en Windows se nos agrega un paquete denominado PythonCOM que nos permite enlazar fácilmente estas dos tecnologías, viene también con una herramienta denominada Makepy que genera código Python que adapta y enlaza la interface COM elegida a nuestro código.
Hay dos formas de ejecutar Makepy:

  • Lanzando el script make.py dentro del directorio win32com.
  • Desde PythonWinToolsCOM Makepy utility. Esta agregaráa autocompletado al código que escribiesemos.

Para enlazar código COM… :?:

import win32com.client
Visum = win32com.client.Dispatch ("visum.visum.11")

Programación web con Python

Configuración de servers

Configurar IIS para que acepte Python

Es lo típico, sólo has de de crear un directorio virtual con permisos para ejecutar CGI's.

  1. Debemos agregar el que pueda ejecutar Python, para ello: Propiedades → Configuración → Asignaciones → Agregar
  2. Escogemos como ruta la del ejecutable de Python.
  3. Para la extensión .py, no?
  • No se nos debe olvidar una cosa importante, debemos agregar en la ruta lo siguiente: %s %s

Quedaría algo así:

C:\Python24\python.exe %s %s

as webs alojadas para Python deben de estar en carpetas en las que dentro de sus nombres no hayan espacios por medio. La siguiente, por ejemplo no serviría:

C:\web de Alfred\

CGI

  • Todo CGI realizado en Python debe empezar por:
print "Content-type: text/html"
print

Es decir, una indicación de que el script mostrará una página web y una línea en blanco de separador.

  • También podemos poner únicamente lo siguiente:
print "Content-Type: text/html\n\n"
  • Un 'Content-Type: text/plain' no procesaría el código html sino que lo mostraría como texto.
  • También podemos mostrar el contenido como xml haciendo:
print "Content-Type: text/xml\n\n"
  • Lo que hace un CGI es ir montando el html, todo lo que sea escrito mediante print será enviado al navegador del cliente.

Errores

Existe un módulo, cgitb, que permite mostrar los errores de los scripts web en python algo más bonitos. Para ello has de importarlo y luego activarlo:

import cgitb
cgitb.enable()

O en una sola línea:

import cgitb; cgitb.enable()

Recoger datos

  • El módulo cgi contiene métodos que recogen los parámetros pasados de una página de forma fácil.
  • Existe el método cgi.FieldStorage() con el que podemos recoger un diccionario con los valores del fórmulario, pero hemos de atender a dos cosas:
    1. Si un campo está vacío no vendrá en el diccionario
    2. Si varios campos tienen el mismo nombre, en vez de venir clave-valor, vendrá clave-lista de valores.
    form = cgi.FieldStorage()
    if not form.has_key('nombre'):
        print "No se ha insertado el nombre.\t"
    else:
        print "Nombre: " + form['nombre'].value
  • Recuerda, si viniese una lista, sería:
list = form.getlist('nombre')
  • O coger sólo el primero:
nombre = form.getFirst('nombre')
  • O podríamos completar el método con algo así:
    form = cgi.FieldStorage()
    if not form.has_key('nombre'):
        print "No se ha insertado el nombre.\t"
    else:
        if type(form['nombre']) ==  type([]):
            for i in range(len(form['nombre'])):
                print "Nombre %d: %s" % (i, form.getlist('nombre')[i])
        else:
            print form['nombre'].value

Formularios .html

  • El tag form tiene varias propiedades que pueden sernos útiles:
    1. action, que indica a qué página se enviará el contenido del formulario
    2. method, al cual se le pasa get o post.
  • La diferencia que radica entre el get y el post es que el get, al pasar la información del formulario lo hace mediante la línea de dirección. El post la pasa implícitamente.
  • Puedes pasar los datos por el método get manualmente, haciendo un link como el siguiente y pasar datos:
form.py?textfield01=aaa
  • Otro ejemplo sería:
http://www.someserver.com/cgi-bin/test.py?param1=value1&param2=value+2 &param3=value%263

Donde:

?	Separa los parámetros de la dirección
&	Separa cada parámetro de otro
+	Representa un espacio en blanco
%26	Es el carácter '&'

Creación de una url para el método get

El módulo urllib contiene utilidades para gestionar direcciones en Python, una de ellas es el método urlencode que pasandole un diccionario te devuelve la serie de parámetros codificados para poner en una url del estilo “GET”. Un código como el que sigue…

    import urllib
    value_dict = { 'param_1' : 'value1', 'param_2' : 'value2' }
    encoded_params = urllib.urlencode(value_dict)
    full_link = "http://www.google.es" + '?' + encoded_params
    print full_link

Colocaría en la viariable full_link el siguiente string:

http://www.google.es?param_1=value1&param_2=value2

Metaclases

Repaso de clases

  • Al crear un objeto de una clase estamos creando una instancia de esta, es decir, una copia en memoria con todas sus propiedades y estructura.
  • Si en la línea de comandos creamos una clase “A” e indicamos que se muestre veremos lo siguiente…
    >>> A
    <class __main__.A at 0x00A21750>

… si luego, de esa clase creamos dos instancias (a y b):

    >>> a = A()
    >>> a
    <__main__.A instance at 0x00A26D50>
    >>> b = A()
    >>> b
    <__main__.A instance at 0x00A26D00>

Podemos imaginar, pues, que no son el mismo objeto, por lo tanto al hacer…

    >>> a==b
    False

El retorno ha sido false, pero en cambio, al comprobar sus propiedades .__class__ vemos que, en efecto, el retorno es true:

    >>> a.__class__ == b.__class__
    True

Queda decir que las clases tienen otro atributo llamado __bases__, es una tupla que contiene una lista de las clases de las que estas heredan.

Qué son las metaclases? (Virtualmente hablando)

Las metaclases son clases que crean otras clases como si fuesen objetos. Imaginemos que existe el comando “metaclass” para definir una clase como si definiesemos una clase cualquiera:

    metaclass A:
        def F (self): pass
        a = ""

Si a python le pidieses que te mostrase A daría:

    >>> A
    <metaclass __main__.A at 2023e4e0>

Si las instanciamos y preguntamos al interprete de Python nos dirá que la instancia es una clase:

    >>> M = A()
    >>> M 
    <class __main__.M at 2022b9d0>

Si creamos luego otro objeto N y preguntamos N == M nos seguirá diciendo que NO son iguales. E imaginemos que podemos hacer una metabase (B) que hereda de la inicial (A), que en vez de __bases__ llamamos a __metabases__.

Notas

In a nutshell

  • Instalar un módulo descomprimido, desde consola: python setup.py install
  • Saber si una variable está declarada:
vars().has_key('variable1')
globals().has_key('variable1')
if not 'variable1' in vars():
  pass

Funciones

  • hex
  • bin (a partir de la 2.6), pasa a binario.

Moverse por el código

General

Ver la documentación de un elemento:

>>> Element.__doc__

Sobre clases

Crear métodos estáticos

Versiones antiguas:

class Callable:
	def __init__(self, anycallable):
		self.__call__ = anycallable
 
class Links:
	def getLastID ():
		links = list(Visum.Net.Links.GetAll)
		return int(links[len(links)-1].AttValue("NO"))
	getLastID = Callable(getLastID)

Versiones nuevas:

class Links:
	@staticmethod
	def getLastID ():
		links = list(Visum.Net.Links.GetAll)
		return int(links[len(links)-1].AttValue("NO"))
script/python/xtra.1316708453.txt.gz · Última modificación: 2020/05/09 09:24 (editor externo)