You are here:GeoTux»Geo-Blogs»Librerías para Geomática»Generación de un archivo instalador en Windows para el visor de PyQGIS

Estadísticas

Invitados: 11
Usuarios registrados: 3133
Usuarios en línea:
-
Registrados hoy:
-

Registro

Redifusión (RSS)

Blogs y Noticias:
Recibe las actualizaciones en Geo-Noticias y Geo-Blogs

Recibir por e-mail
Recibir Geo-Noticias y Geo-Blogs por e-mail

¿Qué es esto?

Lunes 14 de Diciembre de 2009 10:45

Generación de un archivo instalador en Windows para el visor de PyQGIS

Written by  German Carrillo
Rate this item
(1 Vote)

El visor de PyQGIS tiene varias dependencias, como por ejemplo: Python, Qt y Quantum GIS. Es ideal que los usuarios finales puedan utilizarlo sin tener que lidiar con ellas. A través de un script que emplea las utilidades py2exe e InnoSetup, es posible generar un instalador que contiene las dependencias y facilita la distribución de la aplicación en Windows.

Objetivo

 

El objetivo a cumplir es la generación de un archivo instalador para el visor de PyQGIS que contenga todas las dependencias que necesita la aplicación, liberando al usuario de cualquier procedimiento complejo en la instalación. Esto permitirá que los usuarios puedan acercarse a las herramientas libres de manera intuitiva.

 

 

Herramientas a utilizar

 

Para generar el archivo instalador del visor de PyQGIS se utilizarán las herramientas py2exe e InnoSetup.

 

py2exe es una utilidad que se encarga de generar archivos ejecutables de Windows a partir de código en Python. De esta forma, con base en archivos .py se obtienen ejecutables .exe de Windows. Dentro de sus principales características están las siguientes:

 

  • Genera ejecutables que pueden funcionar sin requerir una instalación de Python. py2exe genera un directorio en el que se incluye el ejecutable y sus dependencias, entre ellas, una librería de enlace dinámico (dll) de Python.

  • Cada aplicación puede utilizar una versión particular de Python. Como cada aplicación está vinculada a una dll que corresponde a una versión de Python (por ejemplo, python26.dll), pueden tenerse diferentes aplicaciones en el sistema operativo y cada una de ellas puede funcionar con una versión específica de Python.

  • Es ampliamente configurable a través de parámetros que indican por ejemplo, los paquetes y módulos a incluir, las librerías dinámicas (dll) a ignorar, la compresión y optimización del resultado, entre otros.

 

py2exe genera todos los archivos necesarios para ejecutar la aplicación, sin embargo, para su distribución es conveniente empaquetarlos en un archivo instalador, esa es la función de InnoSetup.

 

InnoSetup es una herramienta que permite obtener por medio de scripts, archivos instaladores personalizados para Windows. Sus principales funcionalidades son:

 

  • Compresión de archivos de la aplicación en un archivo ejecutable de instalación.

  • Generación de accesos directos en el escritorio, en la barra de acceso rápido y en el menú inicio.

  • Generación de archivo de desinstalación.

 

 

Instalación

 

Para instalar py2exe se descarga y ejecuta el archivo correspondiente a la versión de Python instalada en nuestro equipo. La descarga se realiza desde el siguiente enlace: http://sourceforge.net/projects/py2exe/files/

 

Para instalar InnoSetup se descarga y ejecuta uno de los instaladores de la serie Stable release desde aquí: http://www.jrsoftware.org/isdl.php

 

 

Script de QGISLite

 

El proyecto QGISLite de Aaron Racicot utiliza un script que vincula las utilidades py2exe e InnoSetup para producir un archivo instalador a partir de código en Python, todo en un solo paso. El script está compuesto por varias partes:

 

  • Parámetros de configuración para py2exe.

  • Una clase para generar el ejecutable con py2exe y el script de InnoSetup.

  • Un método para compilar el script de InnoSetup para obtener finalemente el instalador (en este método se ejecuta el programa InnoSetup que debe estar preinstalado).

 

Para el instalador del visor PyQGIS se ha modificado el script de QGISLite obteniendo un código personalizado que puede descargarse desde este enlace. El script es el siguiente:

 

1.   # -*- encoding=utf-8 -*-
2.
3. from distutils.core import setup
4. import py2exe
5. import os
6.
7. # Build tree of files given a dir (for appending to py2exe data_files)
8. # Taken from http://osdir.com/ml/python.py2exe/2006-02/msg00085.html
9. def tree(src):
10. list = [(root, map(lambda f: os.path.join(root, f), files)) for (root, dirs, files) in os.walk(os.path.normpath(src))]
11. new_list = []
12. for (root, files) in list:
13. if len(files) > 0 and root.count('.svn') == 0:
14. new_list.append((root, files))
15. return new_list
16.
17. ################################################################
18. class InnoScript:
19. def __init__(self,
20. name,
21. lib_dir,
22. dist_dir,
23. windows_exe_files = [],
24. lib_files = [],
25. version = "1.0"):
26. self.lib_dir = lib_dir
27. self.dist_dir = dist_dir
28. if not self.dist_dir[-1] in "\\/":
29. self.dist_dir += "\\"
30. self.name = name
31. self.version = version
32. self.windows_exe_files = [self.chop(p) for p in windows_exe_files]
33. self.lib_files = [self.chop(p) for p in lib_files]
34.
35. def chop(self, pathname):
36. assert pathname.startswith(self.dist_dir)
37. return pathname[len(self.dist_dir):]
38.
39. def create(self, pathname="dist\\VisorGeografico.iss"):
40. self.pathname = pathname
41. ofi = self.file = open(pathname, "w")
42. print >> ofi, "; WARNING: This script has been created by py2exe. Changes to this script"
43. print >> ofi, "; will be overwritten the next time py2exe is run!"
44. print >> ofi, r"[Setup]"
45. print >> ofi, r"AppName=%s %s" % (self.name, self.version)
46. print >> ofi, r"AppVerName=%s %s" % (self.name, self.version)
47. print >> ofi, r"DefaultDirName={pf}\%s" % self.name
48. print >> ofi, r"DefaultGroupName=%s" % self.name
49. print >> ofi, r"VersionInfoVersion=%s" % self.version
50. print >> ofi, r"VersionInfoCompany=GeoTux"
51. print >> ofi, r"VersionInfoDescription=Visor Geográfico"
52. print >> ofi, r"VersionInfoCopyright=GeoTux"
53. print >> ofi, r"AppCopyright=Germán Carrillo - 2009"
54. print >> ofi, r"AppSupportURL=http://geotux.tuxfamily.org"
55. print >> ofi, r"OutputBaseFilename=Visor_Geografico_GeoTux_Installer"
56. print >> ofi, r"LicenseFile=d:\trabajos\dllo\qgis_python\visor_instalador\licencia.txt"
57. print >> ofi, r"WizardImageBackColor=clBlack"
58. print >> ofi
59. print >> ofi, r"[Languages]"
60. print >> ofi, r'Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"'
61. print >> ofi
62.
63. print >> ofi, r"[Tasks]"
64. print >> ofi, r'Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"'
65. print >> ofi, r'Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"'
66. print >> ofi
67.
68. print >> ofi, r"[Files]"
69. for path in self.windows_exe_files + self.lib_files:
70. print >> ofi, r'Source: "%s"; DestDir: "{app}\%s"; Flags: ignoreversion' % (path, os.path.dirname(path))
71. print >> ofi, r'Source: lib\gdal16.dll; DestDir: {app}\lib; Flags: ignoreversion'
72. print >> ofi, r'Source: lib\QtSvg4.dll; DestDir: {app}\lib; Flags: ignoreversion'
73. print >> ofi, r'Source: lib\proj.dll; DestDir: {app}\lib; Flags: ignoreversion'
74.
75. print >> ofi, r"[Icons]"
76. print >> ofi, r'Name: "{group}\{cm:ProgramOnTheWeb,%s}"; Filename: "http://geotux.tuxfamily.org"' % \
77. self.name
78.
79. for path in self.windows_exe_files:
80. print >> ofi, r'Name: "{group}\%s"; Filename: "{app}\%s"; WorkingDir: {app}' % \
81. (self.name, path)
82.
83. print >> ofi, 'Name: "{group}\Uninstall %s"; Filename: "{uninstallexe}"' % self.name
84. print >> ofi, 'Name: "{commondesktop}\%s"; Filename: "{app}\%s"; Tasks: desktopicon; WorkingDir: "{app}"' % \
85. (self.name, path)
86. print >> ofi, 'Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\%s"; Filename: "{app}\%s"; Tasks: quicklaunchicon; WorkingDir: "{app}"' % \
87. (self.name, path)
88. def compile(self):
89. try:
90. import ctypes2
91. except ImportError:
92. try:
93. import win32api
94. except ImportError:
95. import os
96. os.startfile(self.pathname)
97. else:
98. print "Ok, using win32api."
99. win32api.ShellExecute(0, "compile",
100. self.pathname,
101. None,
102. None,
103. 0)
104. else:
105. print "Cool, you have ctypes installed."
106. res = ctypes.windll.shell32.ShellExecuteA(0, "compile",
107. self.pathname,
108. None,
109. None,
110. 0)
111. if res < 32:
112. raise RuntimeError, "ShellExecute failed, error %d" % res
113.
114.
115. ################################################################
116.
117. from py2exe.build_exe import py2exe
118.
119. class build_installer(py2exe):
120. # This class first builds the exe file(s), then creates a Windows installer.
121. # You need InnoSetup for it.
122. def run(self):
123. # First, let py2exe do it's work.
124. py2exe.run(self)
125.
126. lib_dir = self.lib_dir
127. dist_dir = self.dist_dir
128.
129. # create the Installer, using the files py2exe has created.
130. script = InnoScript("Visor Geografico GeoTux",
131. lib_dir,
132. dist_dir,
133. self.windows_exe_files,
134. self.lib_files)
135. print "*** creating the inno setup script***"
136. script.create()
137. print "*** compiling the inno setup script***"
138. script.compile()
139. # Note: By default the final setup.exe will be in an Output subdirectory.
140.
141. ######################## py2exe setup options ########################################
142.
143. zipfile = r"lib\shardlib"
144.
145. options = {
146. "py2exe": {
147. "compressed": 1,
148. "optimize": 2,
149. "includes": ['sip'],
150. "excludes": ['backend_gtkagg', 'backend_wxagg', 'tcl', 'tcl.tcl8.4', 'Tkinter' ],
151. "dll_excludes": ['libgdk_pixbuf-2.0-0.dll', 'libgobject-2.0-0.dll', 'libgdk-win32-2.0-0.dll', 'phonon4.dll', 'MSVCR80.dll', 'QtScriptTools4.dll', 'tcl84.dll', 'tk84.dll' ],
152. "packages": ["qgis", "PyQt4"],
153. "dist_dir": "dist",
154. }
155. }
156.
157.
158. data_files = tree('plugins') + tree('resources') + [ ( ".", [ "msvcp71.dll", "licencia.txt" ] ) ]
159.
160. setup(
161. options = options,
162. # The lib directory contains everything except the executables and the python dll.
163. zipfile = zipfile,
164. windows=[{"script": "VisorGeografico.py"}],
165. # use out build_installer class as extended py2exe build command
166. cmdclass = {"py2exe": build_installer},
167. data_files = data_files
168. )



Instalador para el visor de PyQGIS

 

Para generar el archivo instalador del visor de PyQGIS seguiremos los pasos que se describen a continuación:

 

1. Descargar insumos

El insumo principal para el ejercicio es el proyecto del visor de PyQGIS que se ha realizado en blogs anteriores (Construcción del visor de PyQGIS y Cargando capas de PostGIS al visor de PyQGIS). El proyecto puede descargarse desde este enlace. Una vez descargado lo descomprimimos en el directorio de trabajo, el script de QGISLite modificado debe estar dentro de la carpeta del proyecto descargado.

 

2. Copiar carpeta de plugins y de resources

Para que la aplicación de PyQGIS pueda funcionar sin tener instalado Quantum GIS en el equipo del usuario final, es necesario tomar de este programa dos carpetas: plugins y resources. La carpeta plugins contiene librerías dll útiles para cargar datos espaciales de formatos convencionales como OGR y PostgreSQL (es decir, los data providers). La carpeta resources contiene información correspondiente a los sistemas de referencia empleados en Quantum GIS.

 

Copiamos las dos carpetas en el directorio de trabajo, cuya estructura debe lucir así:

 

Directorio de trabajo

3. Definir qgis_prefix

Ahora necesitamos que la aplicación de PyQGIS busque las librerías y datos de las carpetas plugins y resources en una ubicación relativa. La variable qgis_prefix del archivo VisorGeografico.py almacena la ruta en la que se buscan dichos datos (ver línea 24 del archivo). Como el archivo y las dos carpetas están en el mismo directorio, la variable qgis_prefix debe ser definida como “.”. Así:

qgis_prefix = '.'

 

4. Personalizar el script py2exe_innosetup.py

Si es necesario, se pueden ajustar algunos parámetros en el script py2exe_innosetup.py.

 

Específicamente se debe revisar el método create de la clase InnoScript, que define los parámetros del script que compilará InnoSetup.

 

5. Ejecutar el script modificado de QGISLite

El script modificado debe ser ejecutado desde la terminal de comandos, de la siguiente forma:

 

python py2exe_innosetup.py py2exe

 

Al ejecutarlo se generan dos carpetas: build y dist. La carpeta build es una carpeta temporal y puede ser borrada sin problemas cuando termina la ejecución del script.

 

La carpeta dist contiene los ejecutables generados y sus dependencias, es decir, en la carpeta dist están los archivos a distribuir. Dentro de la carpeta dist se encuentra una carpeta Output y allí está ubicado el archivo instalador, que luce así:

 

Instalador

 

Conclusiones

 

Es posible distribuir el visor de PyQGIS a través de un archivo instalador para Windows que contiene todas las dependencias requeridas (Qt, Quantum GIS y Python) y que no necesita de una instalación de Python en el equipo del usuario final.

 

 

Referencias

 

 

 

Pdf Puedes descargar este artículo en pdf desde aquí (91 KB).

 

 

 

Last modified on Jueves 29 de Septiembre de 2011 04:31

Comentarios  

 
0 # error al ejecutar scriptAdolfo 17-02-2012 01:44
Hola Germán, he seguido los pasos descriptos arriba, pero obtengo el siguiente error al ejecutar en Windows XP, con Python 2.6, el script py2exe_innosetu p.py py2exe:

ImportError: No module named sip
Responder | Responder con una citación | Citar
 
 
0 # Re:tuxman 17-02-2012 11:25
Hola Adolfo,

resulta complicado colaborarte sin que des mayor información del problema. Te cuento que hace un par de años escribí este post, sin embargo, acabo de reproducirlo en mi equipo y el instalador se generó exitosamente (después de ajustar un par de inconvenientes) .

Estoy usando el instalador OSGeo4W para instalar Python, QGIS, PyQt4, etc.

Cómo has instalado esos paquetes tú y qué versiones instalaste?

El visor funciona cuando lo ejecutas desde la consola de Windows?

Saludos,

Tuxman
Responder | Responder con una citación | Citar
 
 
0 # error al ejecutar scriptAdolfo 25-02-2012 17:36
Hola Germán,

después de dos días de prueba, logré compilar y generar el .exe en Windows XP (32 bit) y 7 (64 bits), pero cuando lo ejecuto da error:

RuntimeError: the PyQt4.QtCore module is version 1 but the qgis.core module requires version -1

Estoy usando el instalador OSGeo4W, última versión, con la respectiva versión de Python y PyQT4.

Viendo un poco en la Web, se ve que la última versión de Quantum Gis no soporta aún la última versión de PyQT4.

Probé con la versión OSGeo4W del tutorial de geotux para configurar un entorno de desarrollo en windows, y me daba error porque faltaba una librería.
Responder | Responder con una citación | Citar
 
 
0 # Re:tuxman 25-02-2012 21:11
Adolfo,

yo también he probado recientemente crear el instalador usando todos los programas desde OSGeo4W, las versiones que he instalado son: QGIS: 1.7.3, PyQt4: 4.8.3, qt4-libs: 4.7.1, Python 2.7 y sip: 4.12.1. En realidad creo que solo elegí la versión de QGIS, el resto se cargaron por defecto.

Por cierto, tuve que resolver uno que otro pequeño problema (que por cierto ya no recuerdo) generando el instalador, pero al final todo salió bien.
Responder | Responder con una citación | Citar
 
 
0 # error al ejecutar scriptAdolfo 25-02-2012 17:36
viene del comentario anterior...

Así que desistí... y ahora estoy intentando compilar en Ubuntu el Quantum Gis, y a partir de allí hacer un ejecutable: http://linfiniti.com/2011/05/building-custom-qgis-installers-for-windows/

Te quería preguntar, porque mi objetivo es hacer una aplicación sencilla que lea un .csv y lo convierta a shape. Después, esta aplicación irá recibiendo nueva funcionalidad, por eso elegí la plataforma qgis.

Cuando se genera el ejecutable, este ocupa 25 mb, y descomprimido, cerca de 100 mb.

Hay alguna forma de achicar este ejecutable?

Quantum Gis es la plataforma correcta, o existen otras más sencillas para leer un .csv y convertirlo a shape?

Gracias y saludos,

Adolfo
Responder | Responder con una citación | Citar
 
 
0 # Re:tuxman 25-02-2012 21:29
Supongo que el ejecutable que compiles con las instrucciones del enlace será más grande aún que el que se genera con py2exe (porque incluyes todo QGIS!).

Para reducirle el tamaño al ejecutable que generas con py2exe basta con borrar algunos archivos (.dll) de la carpeta plugins. Si te fijas, cada archivo tiene el nombre de la función que desempeña, tú podrías dejar de lado varios de esos y eso te quitaría unos 5MB al final. Se me ocurre que puedes remover por ejemplo: wms*, wfs*, sql*, gpx*, oracle*, etc. Veo que en el instalador se incluye además una librería QtWebKit4.dll (carpeta lib) que pesa 10MB, supongo que se puede remover también, para eso debes editar el py2exe_innosetu p.py o editar el archivo de InnoSetup antes de empaquetar todo.

Creo que tienes muchas alternativas, para empezar, necesitas visualizar el shapefile? o solo requieres hacer la conversión de csv a shp? En el caso que necesites la visualización, deben haber muchas soluciones, entre las que conozco están SharpMap y MapWinGIS (del que también publiqué un ejemplo similar para construir un instalador: http://geotux.tuxfamily.org/index.php/es/component/k2/item/97-creacion-de-un-archivo-instalador-para-el-visor-de-shapefiles-de-mapwingis), pero para tomar la decisión averigua el alcance de cada solución y estima cuánto puede crecer tu programa en términos de funcionalidades , por ahora hace esta conversión, luego qué podrá venir? lo soporta la solución que elegiste?

Saludos,

Tuxman
Responder | Responder con una citación | Citar
 

Escribir un comentario


Código de seguridad
Refescar

 

¿Dónde nos leen?