Google+ Seguidores

miércoles, 3 de junio de 2015

Crear un ejecutable .exe en python con cx_Freeze Segunda parte

    30


En este tutorial mi intención es ampliar la información proporcionada en la entrada Crear un ejecutable .exe en python con cx_Freeze creada por Diego Caraballo para solucionar algunas dudas que en su momento me surgieron y seguramente a otros también.

Daré por entendido que ya tienen cx_Freeze instalado correctamente, de no ser así te recomiendo pasarte por la entrada Crear un ejecutable .exe en python con cx_Freeze para su instalación.

Creare 3 ejecutables:
1-Uno sencillo con la pura consola.
3-Ejercicio realizado en Juego en PyGame – PONG por su servidor.

Los dos últimos con interfaz gráfica y recursos externos (imágenes, sonidos, etc).


*Si no tienes realizados los ejemplos, aquí te dejo todos los archivos listos para crear sus ejecutables: Ejemplos

Antes de empezar recomiendo crear un “Path” al intérprete de Python ¿A qué me refiero con esto? bueno cuando lo instalamos en Windows este se aloja por defecto en c:\python27 entonces para ejecutar el intérprete normalmente entraríamos al símbolo del sistema (CMD) y tenemos que escribir toda la ruta donde se encuentra (c:\python27\python.exe) que puede ser muy engorroso. Pues con este “Path” vamos a poder ejecutar el intérprete desde cualquier ubicación en el símbolo del sistema simplemente con escribir “python” tal como lo muestro en el siguiente vídeo:

Esto lo he probado en Windows 7, 8 y 8.1 con éxito, tengo entendido que también funciona en Windows XP y Vista para los que sigan usando estos sistemas operativos.

Otra recomendación es que tus archivos .py que vayas a convertir a .exe los tengas en una carpeta de fácil acceso desde el símbolo del sistema (CMD), por ejemplo C:\proyectos\prueba porque si tienes todo en el escritorio de windows, para llegar a la carpeta desde CMD tendrías que escribir una ruta muy larga.

Ejemplo 1:
Vamos a nuestro editor de texto preferido (el mío Sublime Text 2) y escribimos el siguiente código:

x = raw_input("introduzca su nombre: ")
print
print "hola", x
print
raw_input("Presiona ENTER para terminar.......")

Nada complicado, guardamos (ejemplo: C:\proyectos\prueba\prueba.py)

Ahora necesitamos crear el archivo setup.py y le escribimos lo siguiente:
import cx_Freeze

executables = [cx_Freeze.Executable("prueba.py",
                                   base = None,
                                   icon = None)]

build_exe_options = {"packages": [],
                     "include_files":[]}

cx_Freeze.setup(
    name = "Prueba",
    version = "1.0",
    description = "Prueba",
    options = {"build_exe": build_exe_options},
    executables = executables
    )
En executables ponemos el nombre del archivo a convertir, el parámetro base lo dejamos en None ya que este programa se ejecuta en la consola y no tiene una interfaz gráfica y en icon el icono que tendrá el ejecutable.
*en los ejemplos siguientes utilizaremos base e icon


En build_exe_options; en  packages se le especifican los módulos que utilizamos en nuestro programa (daré más detalles sobre esto en los ejemplos siguientes) y en include_files los recursos como imágenes, sonidos, etc. Ya que este ejemplo no utiliza nada de esto, los dejamos vacíos.

Y finalmente cx_freeze.setup van los datos de nuestro programa como el nombre, versión, una descripción y las características que llenamos al principio.


*puedes conocer mas de todas estas características en la documentación de cx_Freeze

ambos en el mismo directorio
Cuando termines guárdalo en la misma carpeta donde tienes el archivo prueba.py con el nombre setup.py




Enseguida abrimos el CMD, nos posicionamos en la carpeta y escribimos python setup.py build
Comando para crear el ejecutable
Damos ENTER y cuando termine se nos habrá creado una carpeta llamada “build” donde vamos a encontrar nuestro ejecutable:

Carpeta build
Ejecutable creado









Si todo salio bien y ejecutamos el archivo prueba.exe nos aparecerá lo siguiente:
programa funcionando
Este fue sencillo, ahora vamos con el siguiente ejemplo.

Ejemplo 2: Generar un PDF apartir de un sencillo formulario en PyQt

Haremos prácticamente lo mismo que en el ejemplo anterior solo que aquí vamos a hacer algunas modificaciones al archivo setup.py de la siguiente manera:

import cx_Freeze

executables = [cx_Freeze.Executable("formularioPDF.py",
                                 base = "Win32GUI",
                                 icon = None)]

build_exe_options = {"packages": [],
                     "include_files":["formularioPDF.ui"]}

cx_Freeze.setup(
    name = "PDF",
    version = "1.0",
    description = "Formulario a PDF",
    options={"build_exe": build_exe_options},
    executables = executables
    )


En executables  va el nombre del archivo .py a convertir, y ahora en base ponemos “Win32GUI” ya que nuestro programa maneja una interfaz gráfica, si lo dejáramos en None  también funciona pero al ejecutar el archivo .exe nos abriría también la consola la cual no ocupamos (prueba creando el ejecutable con ambas configuraciones para te des cuenta a lo que me refiero).

En build_exe_options aquí pasa algo curioso:
En package  en teoría debemos de incluir todas las librerías que maneja nuestro programa, si te fijas en el código fuente de la aplicación importamos; sys, os, reportlab.pdfgen y PyQt4 las cuales deberíamos de introducir en packages, lo hice la primera vez pero al querer crear el ejecutable, me decía que no podía encontrar un módulo de la librería PyQt4, con las primeras 3 no me daba problemas, así que opte por dejarlo vacío y para mi sorpresa funciono O.O,  investigue un poco sobre el tema y resulta que cx_Freeze añade automáticamente algunas librerías, desafortunadamente no encontré algún tipo de lista de que librerías detecta y cuáles no, por lo que aquí es cuestión de estar probando.

En include_files; ya que tenemos un recurso externo formularioPDF.ui el cual es el que se creó en QtDesigner, así que aquí lo agregamos.

Todo en la misma carpeta

Guardamos (c:\proyectos\PyQt) y nos debe de quedar todo en la misma carpeta.



Ejecutable funcionando
Ahora hacemos los mismos pasos que en el ejemplo 1:

1-Abrimos CMD
2-Nos posicionamos en la carpeta donde tenemos los archivos (cd c:\proyectos\PyQt)
3-Escribimos python setup.py build
4-Se nos genera una carpeta llamada “build
5-Ejecutamos el archivo formularioPDF.exe

Y debe de funcionar sin que se abra la consola, la pura interfaz gráfica.




Aquí antes de crear el archivo setup.py vamos a hacer una ligera modificación al código del juego.

Si realizaste la guía Juego en PyGame – PONG, te acordaras que en la sección “funciones de ayuda” tenemos lo siguiente:
# ============================================================================
# ======================== FUNCIONES DE AYUDA ================================
# ============================================================================
def texto(texto, tam=20, color=(0, 0, 0)):
    fuente = pygame.font.Font(None, tam)
    return fuente.render(texto, True, color)
# ============================================================================
En la línea pygame.font.Font(None, tam) con el parámetro None le decimos que pygame se encargue de cargar una fuente por defecto, pues resulta que a cx_Freeze no le gusta esto y al intentar crear el ejecutable nos marca un error por lo que tenemos que conseguir una fuente y especificársela de la siguiente manera:
# ============================================================================
# ======================== FUNCIONES DE AYUDA ================================
# ============================================================================
def texto(texto, tam=20, color=(0, 0, 0)):
    fuente = pygame.font.Font("arial.ttf", tam)
    return fuente.render(texto, True, color)
# ============================================================================
*Descarga cualquier fuente de Internet y ponla en la misma carpeta.

Y ya que estamos aquí, vamos a la función principal y aprovechamos para ponerle un icono a la ventana del juego de esta manera:


Agregando un icono al juego
En la variable icono cargamos la imagen a mostrar como icono y con pygame.display.set_icon(icono) lo coloca en la ventana. 
*Puedes descargar iconos con extensión .png y .ico de esta pagina: IconArchive

Icono colocado

Si ejecutas veras como el icono aparece en la ventana y en la barra de tareas. Excelente!!!




Ahora sí, creamos el archivo setup.py y lo configuramos de la siguiente manera:
import cx_Freeze

executables = [cx_Freeze.Executable("PONGfinal.py",
                                 base = "Win32GUI",
                                 icon = "icon.ico")]

build_exe_options = {"packages": ["pygame"],
                     "include_files":["arial.ttf",
                                      "pierdes.wav",
                                      "rebote.wav",
                                      "icon.png"]}

cx_Freeze.setup(
    name = "PONG",
    version = "1.0",
    description = "Juego PONG",
    options={"build_exe": build_exe_options},
    executables = executables
    )
En executables en el parámetro icon le asigno el icono que debe ser una imagen .ico que llevara el archivo .exe.

En build_exe_options; en packages  aquí si agregue la librería pygame porque cx_Freeze no me la detecta por si solo y en include_files todos los recursos que utiliza el juego.

A partir de aquí repetimos los pasos:

1-Guardamos (c:\proyectos\Pong), todo en la misma carpeta.
2-Abrimos CMD
3-Nos posicionamos en la carpeta donde tenemos los archivos (cd c:\proyectos\Pong)
4-Escribimos python setup.py build
5-Se nos genera una carpeta llamada “build
6-Ejecutamos el archivo PONGfinal.exe


y wualaa!



Ahora ya puedes presumirle a tus amigos tus creaciones en cualquier computadora sin la necesidad de tener Python instalado.




Nueva información:

Hasta aquí hemos hecho ejemplos que manejan pocos recursos, pero te imaginas que necesites crear el ejecutable de un programa que utilice muchas imágenes, sonidos, fuentes, etc. el problema que sería tener que agregar en include_file cada archivo, sería muy tedioso, pero hay una manera de evitar todo esto y utilizare el ejemplo del PONG para esto.
Carpeta recursos

Vamos al directorio del Pong y vamos a crear una carpeta que llamaremos “recursos” y en ella vamos a meter todos los recursos que usa nuestro juego.


Ahora hay que hacer unas modificaciones al código fuente del Juego para que encuentre esos recursos añadiendo a la ruta de los archivos la carpeta "recursos" de la siguiente manera:

Agregamos la carpeta recursos a la ruta de los archivos que cargamos

Y al archivo setup.py le hacemos la siguiente modificación:
import cx_Freeze

executables = [cx_Freeze.Executable("PONGfinal.py",
                                  base = "Win32GUI",
                                  icon = "recursos\icon.ico")]

build_exe_options = {"packages": ["pygame"],
                     "include_files":["recursos"]}

cx_Freeze.setup(
    name = "PONG",
    version = "1.0",
    description = "Juego PONG",
    options={"build_exe": build_exe_options},
    executables = executables
    )
En icon, le añadimos la nueva carpeta donde se encuentra el archivo icon.ico y en include_files solamente le pasamos la carpeta donde se encuentran todos los recursos.


*Aquí el link a los archivos con las nuevas modificaciones; PONGfinal.py y setup.py

A partir de aquí los pasos para crear el ejecutable con python setup.py build son los mismos.

Pero que tal si te dijera que también puedes crear tu propio instalador (1 solo archivo) listo para ser distribuido e instalado en cualquier computadora O.O y es tan sencillo como escribir python setup.py bdist_msi. Mind Blow!!!

Asi es joven pythonizta en vez de escribir python setup.py build vamos a cambiar el build por bdist_msi.

Creando el instalador
Damos ENTER y cuando termine se nos crearan 2 carpetas; la ya conocida “build” y otra llamada “dist” en la que encontraremos nuestro instalador:
Instalador
Si lo ejecutas debe de iniciar como cualquier instalador poniendote por defecto la ruta de instalacion "C:\Archivos de programa\PONG\":
Instalando nuestra aplicación



Problema por resolver:
cx_Freeze tiene una opción para que el mismo instalador cree un acceso directo al escritorio automáticamente agregando 2 parámetros al setup.py; shortcutName y shortcutDir.


Pero hay un problema......
Al instalar la aplicación si me genera el acceso directo y al querer usarlo me da un error diciéndome que no encuentra los recursos, pero si yo creo el acceso directo manualmente si me funciona.

Al ver las propiedades de ambos accesos directos me encuentro que con el creado por el instalador no pone el parámetro “Iniciar en:” que es el que necesita para funcionar.
Y hasta el momento no he encontrado cómo hacer para que cx_Freeze me agregue este parámetro automáticamente. Si alguien encuentra la manera antes que yo se lo agradecería mucho.

Saludos! (◕‿◕)


Salvador Ramirez  Google+

30 comentarios:
Write comentarios
  1. Tal vez esto les interesa también
    https://youtu.be/Jz2YruNdyzs

    ResponderEliminar
    Respuestas
    1. Gracias por el Material Alberto y gracias también por visitar el blog y participar ;)
      Saludos

      Eliminar
    2. Gracias por el dato, no sabia que cx_Freeze con poner el nombre de la carpeta donde tengas todos los recursos es suficiente, con esto te evitas poner cada archivo que use tu programa, ya lo probé con el setup.py que pongo en la entrada y funciono.

      De hecho en la documentación de cx_Freeze dice que se puede hacer, pero lo pase por alto. xD

      Y efectivamente con:

      python setup.py bdist_msi

      Se genera un instalador al que puedes especificarle donde se instale que por defecto te pone C:\Program Files (x86)\PONG\ (en el caso del Pong)

      Voy a actualizar la entrada con esta información.

      Eliminar
  2. Interesantísimo.

    Alguien sabe como aligerar el archivo ? Guarda cantidad de localizaciones geográficas de todo el mundo que multiplica el peso del archivo. Como se excluyen esos archivos ?
    Gracias.

    ResponderEliminar
    Respuestas
    1. Pues eso ya dependerá de los recursos y librerías que utilices y he notado que si creas el instalador el peso se reduce bastante si lo comparas con crear solo el .exe.
      Aparte cx_Freeze tiene dos parámetro; "compress" y "compressed "que no he probado y talvez influyanen el peso final del archivo.

      Eliminar
  3. Hola! Me gustaria saber si teneis en mente crear un PDF con todos los temas del blog. Esta claro que uno mismo lo puede hacer. Pero vosotros, mejor que nadie, podeis crear un orden de aprendizaje. Me refiero a ir ordenando los temas dentro de ese PDF por progresividad de dificultad. O poner un boton de download donde uno se pudiera descargar el tema escogido y los archivos adjuntos (si se trata de juegos o ejercicios). Gracias!

    ResponderEliminar
    Respuestas
    1. Bueno, eso ya depende de Diego Caraballo que es el dueño del Blog.

      Eliminar
    2. Hola, primero que nada gracias por visitar el blog y participar en el. Lo de poder descargar el PDF de cada entrada voy a ver si lo podemos implementar. Por ahora lo que preguntas sobre el orden de dificultad solo está pensado para el Tutorial Python desde cero, los demás son artículos que nos parecen relevantes para compartir. Saludos

      Eliminar
  4. Ah, se me olvidaba. En este enlace tambien viene una explicacion muy buena sobre la creacion de ejecutables (su creador es Jesús Conde):

    https://youtu.be/Ro4z4xFhlo4

    ResponderEliminar
  5. Hola,

    Llevo bastante tiempo leyendo tu blog ya que estoy desarrollando en el trabajo una GUI para robocopy usando pyQT. El caso es que no consigo que me lo compile a exe. Me tira un pila de errores, me genera los archivos pero nada de nada.

    Traceback (most recent call last):
    File "setup.py", line 16, in
    executables = executables
    File "C:\Python27\lib\site-packages\cx_Freeze\dist.py", line 362, in setup
    distutils.core.setup(**attrs)
    File "C:\Python27\lib\distutils\core.py", line 151, in setup
    dist.run_commands()
    File "C:\Python27\lib\distutils\dist.py", line 953, in run_commands
    self.run_command(cmd)
    File "C:\Python27\lib\distutils\dist.py", line 972, in run_command
    cmd_obj.run()
    File "C:\Python27\lib\distutils\command\build.py", line 127, in run
    self.run_command(cmd_name)
    File "C:\Python27\lib\distutils\cmd.py", line 326, in run_command
    self.distribution.run_command(command)
    File "C:\Python27\lib\distutils\dist.py", line 972, in run_command
    cmd_obj.run()
    File "C:\Python27\lib\site-packages\cx_Freeze\dist.py", line 232, in run
    freezer.Freeze()
    File "C:\Python27\lib\site-packages\cx_Freeze\freezer.py", line 610, in Freeze

    self.compress, self.copyDependentFiles)
    File "C:\Python27\lib\site-packages\cx_Freeze\freezer.py", line 588, in _Write
    Modules
    self._CopyFile(module.file, target, copyDependentFiles)
    File "C:\Python27\lib\site-packages\cx_Freeze\freezer.py", line 143, in _CopyF
    ile
    for source in self._GetDependentFiles(source):
    File "C:\Python27\lib\site-packages\cx_Freeze\freezer.py", line 263, in _GetDe
    pendentFiles
    dependentFiles = cx_Freeze.util.GetDependentFiles(path)
    cx_Freeze.util.BindError: (11, 'Se ha intentado cargar un programa con un format
    o incorrecto', 'C:\\Python27\\lib\\site-packages\\PyQt4\\uic\\port_v3\\proxy_bas
    e.py')

    ResponderEliminar
    Respuestas
    1. Hola, gracias por visitar el blog. Espero Salvador Ramírez te pueda responeder, fue el creador de la entrada. Saludos

      Eliminar
    2. Este comentario ha sido eliminado por el autor.

      Eliminar
    3. Buenos días

      Gracias por responder tan rápido. Aqui mi código de setup.py

      import cx_Freeze


      executables = [cx_Freeze.Executable("robogui.py",
      base = "Win32GUI",
      icon = "robo.ico")]

      build_exe_options = {"packages": ["shutil"],
      "include_files":["robogui.ui"]}

      cx_Freeze.setup(
      name = "RobocopyGUI",
      version = "1.0",
      description = "Robocopy con interfaz grafica",
      options={"build_exe": build_exe_options},
      executables = executables
      )

      Me acabo de fijar que en el link de este post pone para python 3 y yo uso el 2.7.

      Saludos.

      Eliminar
    4. 1.- Se supone que el error:
      cx_Freeze.util.BindError: (11, 'Se ha intentado cargar un programa con un format
      o incorrecto', 'C:\\Python27\\lib\\site-packages\\PyQt4\\uic\\port_v3\\proxy_bas
      e.py')

      era un bug de cx_Freeze que ya fue corregido, cerciórate de que tienes instalada la ultima versión.

      2.- prueba cambiando el nombre de la carpeta "port_v3" y trata de nuevo de crear el ejecutable.

      3.- Prueba poniendo y quitando las librerías que usa tu código (import) en "packages"

      Si nada de lo anterior te funciona me gustaría tratar de crear el exe yo, pero tendrías que compartirme tu código fuente.

      Saludos

      Eliminar
    5. Tenía la versión 4.3.3. He actualizado a la 4.3.4 y ha salido bien. La pena es que ahora no me funciona el programa bien por culpa del unicode. Si lo ejecuto como .py me descodifica bien las ñ y las tildes. Pero una vez compilado vuelvo a tener problemas con el unicode. ¿Porque si lo ejecuto como script (.py) funcionan los unicode y cuando lo convierte a exe se va todo al garete?. Muchas gracias por tu ayuda Salvador.

      Eliminar
    6. Asegúrate que al principio de tu script (linea 1) tengas esto:

      #! encoding: utf-8

      y siempre anteponer una "u" antes de cualquier texto que utilice caracteres especiales como la "ñ" o los acentos, por ejemplo:

      texto1 = u"ñapindá" <--- una "u" antes del texto

      texto2 = "palabra" <-- si el texto no utiliza caracteres especiales no hay necesidad de añadir la "u"

      Espero esto resuelva tu problema

      Eliminar
    7. En el caso del QT Designer, verifica que tengas configurado correctamente el lenguaje, yo he puesto la ñ y acentos, y me los muestra correctamente ya sea ejecutando el script.py o el .exe

      Eliminar
    8. Siempre tengo puesto el comentario de codificación. Ya tuve bastantes problemas con el encoding en python. Mi programa es muy simple. Botón seleccionar origen para seleccinar una carpeta y un botón seleccionar destino. Ayer no podia seleccionar un directorio con carácteres latinos (ñ, diéresis, tildes). Ya lo he solucionado pero ahora al clicar el botón copiar no me hace nada si la ruta contiene carácteres latinos. Y como no hay consola, no se porque da el error. No le puedo poner u delante porque la ruta se construye mediante variables. He probado a forzar el encoding haciendo origen.decode('latin-1') que es como me ha funcionado hasta ahora. En las preferencias de QT he configurado el idioma como latín pero sigue sin funcionar. Se ejecuta pero a la hora de copiar no hace nada. ¿Hay alguna forma de que al convertir a exe me muestre la GUI de mi app y la consola para ver los errores?

      Muchas gracias por tu ayuda Salvador.

      Un saludo.

      Eliminar
    9. En el archivo setup.py en el parámetro:

      base = "Win32GUI"

      cámbialo por:

      base = None

      Crea de nuevo el exe y al ejecutarlo se abrirá la consola junto a tu aplicación donde podrás ver que error tienes.

      Eliminar
  6. !!!!!maravilloso¡¡¡¡¡¡ un millón de gracias

    ResponderEliminar
  7. Ayuda me da ese error y no he logrado resolverlo gracias?
    running build
    running build_exe
    error: [Errno 2] No such file or directory: 'Sin t\xc3\xadtulo 0'

    ResponderEliminar
  8. Tengo un problema y espero que usted me pueda ayudar y es que he creado una aplicación que me permite guardar datos en un archivo de texto y funciona muy bien cuando esta como .py, pero cuando lo convierto a ejecutable tengo problemas con las ñ y las tildes entre otros acentos que no pertenecen al formato ASCCI. HAY ALGUNA SOLUCIÓN A ESTE PROBLEMA, LE AGRADEZCO SU AYUDA...

    ResponderEliminar
    Respuestas
    1. Asegúrate que al principio de tu script (linea 1) tengas esto:

      #! encoding: utf-8

      y siempre anteponer una "u" antes de cualquier texto que utilice caracteres especiales como la "ñ" o los acentos, por ejemplo:

      texto1 = u"ñapindá" <--- una "u" antes del texto

      texto2 = "palabra" <-- si el texto no utiliza caracteres especiales no hay necesidad de añadir la "u"

      Espero esto resuelva tu problema

      Eliminar
  9. Hola tengo un problema en ejecutar .exe compilados con cx_freeze a partir de un .py y ejecutarlos en distintas versiones de Windows, estos no tienen instalado python......Puede que el error de se por que les hace falta la instalación de python y la librerías que utilizo?

    El .exe esta compilado en windows, pero cuando lo ejecuto en otra maquina virtual con la misma versión me dice DLL load failed: No se puede encontrar el modulo especificado y me hace referencia a kinterbasdb ERROR

    ImportError: DLL load failed: This application has failed to start because the a

    pplication configuration is incorrect. Reinstalling the application may fix this

    problem.

    ResponderEliminar
  10. Hola, disculpa intento crear un ejecutable, pero importo algunas cosas de otro archivo .py, pero no se como hacerlo ejecutable, en total manejo 3 archivos .py y estan conectados entre ellos. Espero que me puedas ayudar.

    ResponderEliminar
  11. Hola muchas desde ya muchas gracias.
    Todo corre bien pero el ejecutable generado solo da una ventana DOS y desaparece al instante sin mostrar nada mas.

    ResponderEliminar

Tu comentario es importante y nos motiva a seguir escribiendo...

Entradas más recientes

© 2014 Mi diario Python. Designed by Bloggertheme9 | Distributed By Gooyaabi Templates
Powered by Blogger.