Entries for Python
Simular enumeraciones en Python
14 May 2012
Estoy ahora mismo trabajando con Python y me acabo de encontrar que disponer de una enumeración me vendría muy bien. Así que, después de investigar un rato, he encontrado dos formas distintas y muy prácticas para hacer enumeraciones.
Estilo C
La primera opción, es hacerlas como se hacen en C. Variables enteras globales:
(GATEWAY_CLASS, FORWARDING_CLASS, PARSE_CLASS) = range(1, 4)
El problema de esta solución, es que en cualquier momento se puede modificar el valor de cualquiera de estas variables, con las consecuencias que esto conlleva.
Estilo Java
En Java, cuando declaramos una enumeración, debemos acceder a través del nombre de la enumeración. Por tanto, para simular este comportamiento en Python, necesitamos una clase:
class RoutingClassType(type):
(GATEWAY_CLASS,
FORWARDING_CLASS,
PARSE_CLASS) = range(1, 4)
Así, ahora tendríamos que acceder así:
RoutingClassType.GATEWAY_CLASS
Aunque esta solución sigue presentando el mismo problema que la solución anterior, lo podemos solucionar creando un nuevo tipo que impida modificar sus atributos:
class EnumType(type):
def __setattr__(self, name, value):
raise ValueError
Y ahora bastará con definir nuestra enumeración de la siguiente forma:
class RoutingClassType(type):
__metaclass__ = EnumType
(GATEWAY_CLASS,
FORWARDING_CLASS,
PARSE_CLASS) = range(1, 4)
SystemError: error return without exception set
11 April 2012
Esto se puede deber a que se ha devuelto NULL en una función en la que se debería devolver algo (None por ejemplo):
static PyObject*
example(PyObject *self, PyObject* args, PyObject* kwargs)
{
// do something
return NULL;
}
se corrige de la siguiente forma:
static PyObject*
example(PyObject *self, PyObject* args, PyObject* kwargs)
{
// do something
Py_RETURN_NONE;
}
o porque al lazar una excepción, no hemos indicado de que excepción se trata:
static PyObject*
example(PyObject *self, PyObject* args, PyObject* kwargs)
{
PyObject* var;
// ...
if(!PyBool_Check(var))
{
return NULL;
}
}
y se corrige:
static PyObject*
example(PyObject *self, PyObject* args, PyObject* kwargs)
{
PyObject* var;
// ...
if(!PyBool_Check(var))
{
PyErr_SetString(PyExc_TypeError, "Not boolean");
return NULL;
}
}
Bindings Python para bibliotecas C: Argumentos (Parte 4)
28 March 2012
Continuando con el ejemplo de ayer, hoy voy a explicar cómo podemos parsear los parámetros de entrada. El estado actual es que hemos definido unos prototipos y los hemos añadido al módulo. Ahora vamos a darle contenido a las funciones add y hello.
Ejemplo en GitHub: mema_methods.
Argumentos en Python
28 March 2012
Para los programadores de C, C++, Java, ... puede resultar un tanto extraño la forma de gestionar los parámetros que tiene Python.
Voy a explicar en esta entrada los tipos de parámetros y cómo podemos hacer uso de ellos.
Bindings Python para bibliotecas C: Métodos (Parte 3)
27 March 2012
Ayer explicaba cómo se monta una estructura básica para crear un módulo. Pero para que el módulo sirva para algo, tendremos que añadir funciones.
Ahora vamos a ver cómo podemos crear nuevas funciones y cómo integrarlas al módulo mema. El objetivo para hoy será crear dos funciones: hello y add.
El resultado debería ser algo similar a lo siguiente:
>>> import mema
>>> mema.hello()
Hello mema!
>>> mema.hello('Vicente')
Hello Vicente!
>>>
>>> from mema import add
>>> add(1, 2)
3
>>> add(400, 4)
404
>>>
Ejemplo en GitHub: mema_methods.
Bindings Python para bibliotecas C: Módulos y compilación (Parte 2)
26 March 2012
La semana pasada empecé ha hablar sobre los Bindings en Python. Hoy vamos a ver cómo es una estructura muy básica, cómo compilar y probar que todo funciona.
Un problema que me estoy encontrando, es que el API C de Python ha ido cambiando con las versiones. Entonces, muchos ejemplos que he encontrado no compilan y hay código muy diferente por ahí.
Inicialmente voy a centrarme en Python 2.7 (última versión de la rama 2.x) y si encuentro tiempo, haré lo mismo para Python 3.
Ejemplo en GitHub: mema_bare.
Bindings Python para bibliotecas C: ¿Qué son? (Parte 1)
23 March 2012
Hoy voy a hablar acerca de bindings para Python. Un binding es un módulo Python, escrito en lenguaje C, que permite realizar llamadas a funciones en C desde un script hecho en Python. Se puede ver como un "puente" desde C a Python.
Pueden existir distintos motivos para desear hacer un binding. En principio, puede parecer un poco contraproducente, ya que se pierde portablidad
Entonces, ¿por qué crear un binding? Bien es sabido por todos que C es más eficiente que Python, por tanto, si se trata de una parte crítica de una aplicación, perfectametne se puede hacer el procesamiento en C y dejar Python para la lógica.
Otra razón es aprovechar código existente en C. Como comenté, estoy trabajando en libemqtt, la cuál está escrita en C. Podría hacer una nueva implementación completa en Python, pero teniendo el código disponible, lo lógico es hacer un binding.
Los próximos días intentaré escribir una pequeña guía sobre cómo hacer un binding para esta bibliotecta.
Actualización (27/03/2012): He creado un repositorio en GitHub con los ejemplos que estoy implementando:
https://github.com/menudoproblema/menudoproblema-examples/tree/master/python/bindings
Validación de NIFs y CIFs en Python 3
24 February 2012
OnlyGL
2 February 2012
Últimamente he estado bastante liado, entre el trabajo, la carrera y el máster apenas tengo tiempo para escribir.
Como resultado de unas prácticas de una asignatura, Diseño Asistido por Computador, he desarrollado un pequeño Framework en Python con OpenGL cuyo objetivo es desarrollar escenas 3D de forma rápida y sencilla. En unas pocas líneas de código podemos ver los resultados rápidamente.
He liberado el código fuente del Framework y está disponible en GitHub: OnlyGL. Aunque en principio no tengo intención de seguir evolucionando OnlyGL, acepto sugerencias y no tengo problema en invertir algún tiempo si alguien está interesado en algo concreto.
Capturar señales en Python
9 December 2011
A continuación dejo un pequeño ejemplo de como se pueden capturar señales con Python:
import signal
import time
import sys
def signal_handler(sig, func=None):
print 'SignalHandler. Saliendo...'
sys.exit(0)
if __name__=='__main__':
signal.signal(signal.SIGTERM, signal_handler)
print 'Esperando 15 segundos...'
time.sleep(15)
print 'Finalizado'
La idea es muy simple, el programa espera 15 segundos y finaliza. Si se envía la señal SIGTERM (señal 15) el proceso terminará sin esperar. Veamos como se ejecuta de forma normal:
$ python test.py
Esperando 15 segundos...
Finalizado
Y aquí podemos ver cómo se capturan las señales y se finaliza antes el proceso:
$ python test.py &
[1] 8172
Esperando 15 segundos...
$ kill -15 8172
SignalHandler. Saliendo...
[1]+ Hecho python test.py
$
Analizar los parámetros de consulta de URL en Python
11 August 2011
>>> from urlparse import urlparse
>>> url = urlparse('http://www.google.com/search?client=ubuntu&channel=fs&q=python')
>>> params = dict([part.split('=') for part in url[4].split('&')])
>>> params
{'channel': 'fs', 'client': 'ubuntu', 'q': 'python'}
Soporte para JPEG, Zlib y FreeType2 en PIL
26 April 2011
Hace unos días escribía como Compilar PIL dentro de VirtualEnv, pero realicé la compilación sin soporte para JPEG, Zlib o FreeType2. Ahora mismo estaba probando un script y me he encontrado el siguiente error:
ImportError: The _imagingft C module is not installed
Este error se debe a que no hay soporte para FreeType2. Revisando el directorio de instalación (donde están los fuentes) me he econtrado con lo siguiente:
--------------------------------------------------------------------
PIL 1.1.7 SETUP SUMMARY
--------------------------------------------------------------------
version 1.1.7
platform linux2 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
[GCC 4.5.2]
--------------------------------------------------------------------
*** TKINTER support not available
*** JPEG support not available
*** ZLIB (PNG/ZIP) support not available
*** FREETYPE2 support not available
*** LITTLECMS support not available
--------------------------------------------------------------------
Al final he optado por la solución más sencilla. Instalarlo en el sistema y utilizarlo dentro de VirtualEnv. Para ello:
$ cd /path/to/virtualenv
$ ln -s /usr/lib/python2.7/dist-packages/PIL/ lib/python2.7/site-packages/
Instalando PIL dentro de VirtualEnv
20 April 2011
A la hora de instalar PIL dentro de VirtualEnv me he encontrado con el siguiente problema:
(ENV)~/ENV$ easy_install pil
Searching for pil
Reading http://pypi.python.org/simple/pil/
Reading http://www.pythonware.com/products/pil
Reading http://effbot.org/zone/pil-changes-115.htm
Reading http://effbot.org/downloads/#Imaging
Best match: PIL 1.1.7
Downloading http://effbot.org/media/downloads/PIL-1.1.7.tar.gz
Processing PIL-1.1.7.tar.gz
Running PIL-1.1.7/setup.py -q bdist_egg --dist-dir /tmp/easy_install-3H1mTt/PIL-1.1.7/egg-dist-tmp-eVNOlg
WARNING: '' not a valid package name; please use only.-separated package names in setup.py
_imaging.c:75:20: fatal error: Python.h: No existe el fichero o el directorio
compilation terminated.
error: Setup script exited with error: command 'gcc' failed with exit status 1
El problema radica en que PIL es que parte está escrita en C, por lo que es necesario compilarlo previamente.
Generar un fichero XML con DOM
6 April 2011
Ayer hablaba un poquito en general acerca de distintos tipos de interfazces para parsear documentos XML. Hoy he preparado un par de ejemplos de como generar un documento XML.
Los ejemplos están hechos en Python, el cuál es ideal para mostrar su funcionamiento. Esto se debe a que Python incluye en su librería estándar un módulo xml, por lo que no es necesario instalar nada extra. Además he utilizado el módulo xml.dom.minidom. minidom es una implementación ligera de la interfaz DOM, cuyo objetivo es ser más rápido y ligero.
Los ejemplos están disponibles aquí.
Parsear una web con sax y python directamente
4 April 2011
Para quien no lo conozca, SAX es una interfaz parsear XML y está disponible en la librería estándar de Python. Últimamente estoy trabajando mucho con parsers XML, así que si el tiempo lo permite escribiré algún artículo más sobre el tema.
Para parsear una url, sin necesidad de descargarla previamente y luego parsearla, podemos apoyar el parser, xml.sax, en urllib2:
import urllib2
import xml.sax
class MiHandler(xml.sax.ContentHandler):
def startElement(self, name, attrs):
print name
parser = xml.sax.make_parser()
parser.setContentHandler(MiHandler())
feed = urllib2.urlopen("http://www.menudoproblema.es/feeds/latest/")
parser.parse(feed)
La teoría es cuando crees saber algo, pero no funciona.
La práctica es cuando algo funciona, pero no sabes por qué.
Los programadores combinan la teoría y la práctica:
Nada funciona y no saben por qué.
