====== 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)
==== 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,
==== 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)
===== Sockets =====
* [[code:tools#sockets|Explicación de 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 ====
- Crear un socket con ''socket.socket''.
- 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()
* Otro ejemplo: {{script:python:example.server.zip|}}
===== 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.
- Debemos agregar el que pueda ejecutar Python, para ello: Propiedades -> Configuración -> Asignaciones -> Agregar
- Escogemos como ruta la del ejecutable de Python.
- 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:
- Si un campo está vacío no vendrá en el diccionario
- 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:
- action, que indica a qué página se enviará el contenido del formulario
- 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¶m2=value+2 ¶m3=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¶m_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
... 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
Si las instanciamos y preguntamos al interprete de Python nos dirá que la instancia es una clase:
>>> M = A()
>>> M
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 ====
* Para más info. mira los [[script:python:docs#metaclases|documentos de metaclases]].
===== 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"))