Trading Bots vs Arbitrage Bots
- Python: el intérprete, actualmente en su versión 2.4.
- Extensiones para win32.
- py2exe: extensión de distutils para generar un .exe a partir de un script python.
- Glade para win32. En ese paquete también viene una versión actualizada de GTK para windows. Si no se puede descargar de la página de GIMP para windows.
- PyGTK para win32. Incluye soporte para glade.
- SQLite y el correspondiente binding para python. SQLite es un motor empotrado de bases de datos muy simple y rapidico. Como el motor de un MSAccess, pero multiplataforma. Creo que con instalar el binding es suficiente (parece que lleva el motor compilado estáticamente), pero no tengo tiempo de hacer pruebecicas así que por eso pongo los 2 enlaces.
- mxDateTime. Librería para manejar fechas. La necesita SQLite.
Teniendo todo esto instalado, ejecutar scripts python en windows no plantea excesivos problemas. Sólo hay que tener algo de cuidado con los encodings por defecto al hacer llamadas a funciones de dlls externas. Los problemas vienen cuando quieres tener un ejecutable que no dependa de una instalación del intérprete. Supondré que el código de mis scripts está en $SRC y la interfaz glade en $SRC/glade.
Para tener un ejecutable independiente hay que crear un fichero $SRC/setup.py que contenga:
from distutils.core import setup
import py2exe
import glob
setup(
name="programa",
#console=["Recetillas.pyw"],
windows=["programa.py"],
data_files=[
("programa.conf"), # configuración que se lee luego con ConfigParser
("datos.db"), # base de datos sqlite
("glade", glob.glob("glade/*.*"))] # interfaz de usuario
)
En ese script está toda la información que py2exe necesita para fabricar un ejecutable de windows. Si os fijais se ve un parámetro windows=["script.py"]. Ahí le decimos a py2exe que genere un ejecutable de windows. Si queremos un ejecutable de consola con su ventanica para ir imprimiendo mensajes de depuración y tal pues ponemos el parámetro console=["script.py"].
Ejecutamos:
En la versión py2exe que tengo creará por defecto un directorio con el ejecutable en $SRC/dist. El parámetro final es para indicarle a py2exe que incluya dentro del ejecutable el paquete "encodings" que luego
necesitaré para las cadenas de texto que usen tildes o eñes. Por cierto, en una aplicación python más o menos portable hay que tener muy en cuenta el encoding por defecto del sistema donde se está ejecutando. La librería de python se configura ella solita como 'ascii' y luego elimina la función que te permite cambiarlo :-? Así que lo mejor es averiguar cuál es el nuestro y ponerlo explícitamente en las conversiones. Para conseguir el encoding por defecto:
loc = locale.getdefaultlocale()
if loc[1]:
default_encoding = loc[1]
Y luego en cada cadena que imprimamos o pasemos como parámetro a funciones que no soporten unicode:
En concreto, el encoding usado en los windows en español que he probado (desde 98 a XP) es cp1252.
Otro detalle. Para que nuestra aplicación vaya bien con unicode en windows 9x hay que instalar el ficher unicows.dll en el directorio de python de la máquina donde estamos generando el ejecutable. py2exe es muy listo y fabrica un unicodedata.pyd en el directorio $SRC/dist para dar soporte unicode a máquinas con versiones antiguas de windows.
No sé si por usar el parámetro console=... el ejecutable falló al no encontrar una dll llamada msvcr71.dll. Copiándola a $SRC/dist se soluciona el problema.
Superado el problema de los encodings, vamos a GTK. py2exe no instala correctamente ciertos módulos de la distribución de GTK como pango o atk. En ese caso hay que copiarlos a mano al directorio $SRC/dist. Se ncuentran en $PYTHON/Lib/site-packages/gtk-2.0/*.pyd. Si se usan gráficos JPG o PNG también habrá que copiar a mano las dlls correspondientes desde $GTK/bin.
No hemos terminado aún. Para que GTK funcione necesita tener a la mano los directorios $GTK/etc (configuración de fuentes y módulos de pango), $GTK/lib (dlls con los módulos de pango) y $GTK/share (temas y demás). La solución es tan simple como copiar estos directorios desde la ubicación original de la instalación de GTK al directorio $SRC/dist. Seguramente se puede hilar más fino y eliminar muchos de los archivos de esos directorios, pero ganas no tengo de ponerme.
Otro detalle añadido. Aunque no he podido mirar por qué pasa, si se pone el típico código GTK la cosa falla
pygtk.require("2.0")
import gtk
La solución chapucera es quitar el require.pygtk("2.0"). Seguiremos investigando :)
Después de seguir todos estos pasos, en el directorio $SRC/dist tenemos un bonico programilla que ya es capaz él solito de andar por el mundo (al menos por los windows).
Por último pongo algunos enlaces que me han resultado muy interesantes a la hora de fabricar el ejecutable. Queda como ejercicio para el lector el fabricar un instalador con InnoSetup o NSIS (a mi realmente no me hacía falta).