Crear un app para MacOS con Intel y Apple Silicon (M1/M2) en Python

Código práctico

Crear tu aplicación .app para macOS (Intel y M1)

Modificaciones en el código para crear la app MisContactos en macOS Intel y Apple Silicon (M1/M2)

Resumen: Guía paso a paso para adaptar tu proyecto PyQt6 y generar un archivo .app en macOS, compatible con procesadores Intel y Apple Silicon (M1/M2).


Modificaciones en el código para crear de la aplicación de ejemplo del libro Python Práctico un archivo .app para Mac con procesadores x86_64 y procesadores de la serie M

1.- Crear la clase ResourceManager.py para obtener la ruta absoluta.

2.- En v_contactos.py hay que quitar la asignación de iconos a los botones, líneas 59, 65, 71, 77, 83 y 91.

3.- En v_main.py quitar la asignación de iconos a los botones, líneas 24, 31, 38.

4.- En v_splash.py cambiar la asignación de imagen por:

Código práctico

5.- En v_telefonos.py quitar la asignación de iconos a los botones, líneas 53, 59, 65.

6.- En PantallaContactos.py cambiar la asignación de iconos a los botones por:

Código práctico

En el método toggle_grabacion_voz y actualizar_texto_con_voz hay que cambiar la asignación de los iconos a los botones utilizando el método icono_qt de la clase ResourceManager.

7.- En PantallaMain.py cambiar la asignación de iconos a los botones por:

Código práctico

Y cambiar el código del método cambiar_idioma por:

Código práctico

8.- En PantallaSplash.py modificar en el método __init__ la asignación de la imagen.

Código práctico

9.- En PantallaTelefonos.py cambiar la asignación de iconos a los botones por:

Código práctico

10.- En Principal.py en el método open_main_window, añadimos la línea 46 para mantener la referencia.

Código práctico

11.- En Conexion.py hemos de llamar al método obtener_ruta_db, para obtener la ruta correcta para la creación de la base de datos. Modificaremos el método __init__ para cambiar la conexión a la base de datos de la línea 14, por la llamada a la función obtener_ruta_db quedando el código de la siguiente manera:

Código práctico

12.- En Mensajes.py modificar el método __init__ de la clase MiMessageBox para cambiar la asignación del icono de la siguiente manera:

Código práctico

13.- Crear archivo build.spec para generar el archivo .app con el código siguiente:

Código práctico
Código práctico
Código práctico
Código práctico

14.- Ejecutar desde el terminal el siguiente comando:

Código práctico

Este comando creará los directorios build y dist con los archivos necesarios. En dist encontraras el archivo MisContactos.app.

15.- Para abrir el archivo MisContactos.app ejecutar desde el terminal el siguiente comando:

Código práctico

Si al ejecutar la aplicación se cerrara de forma inesperada, tendríamos que añadir un archivo log para ir grabando los pasos y poder detectar donde se produce el error.

16.- Añadir código para crear archivo log. En Principal.py añadimos las líneas 39 y 40.

Código práctico

Y en el método open_main_window añadiremos la línea 47.

Código práctico

En PantallaMain.py haríamos la importación de logging (línea 10) y en el método __init__ añadiremos las líneas 16 y 17.

Código práctico

De esta forma iremos poniendo mensajes para saber por dónde ha pasado correctamente y donde ha fallado.

17.- Para saber el contenido del archivo .log desde el terminal ejecutaremos el siguiente comando:

Código práctico

Explicación archivo .spec

Explicación del archivo build.spec

Código práctico

Esto indica que el archivo es Python y usa codificación UTF-8.

Código práctico

Utilizaremos block_cipher para cifrar archivos con clave si se usan contraseñas. En nuestro caso, está desactivado.

Código práctico

Analysis es el objeto que analiza el script principal (Principal.py) y detecta sus dependencias (módulos, recursos, etc.).

pathex=[] Lista de rutas adicionales donde buscar módulos.

binaries=[] Archivos binarios adicionales a incluir (por ejemplo, DLLs o .dylib en Mac).

datas=[] Archivos de datos como .ui, .png, .db, etc. que necesita la aplicación en nuestro caso incluimos las imágenes y las traducciones.

hiddenimports=[] Para añadir los módulos que no se detectan automáticamente y necesitas forzar su inclusión. En nuestro caso los de reconocimiento de voz y los PyQt6.

hookspath=[] Rutas personalizadas para tus propios «hooks». Son scripts de Python que le indican a la herramienta qué incluir en la aplicación final, como archivos de datos o módulos de importación ocultos, para así garantizar que la aplicación funcione correctamente

hooksconfig={} Configuración específica para esos hooks.

runtime_hooks=[] Son scripts que se ejecutan justo antes de iniciar tu aplicación. Se utilizan para cambiar rutas, variables de entorno, etc.

excludes=[] Aquí añadiremos los módulos que quieres excluir manualmente del bundle.

win_no_prefer_redirects=False. Deshabilita la preferencia del sistema operativo Windows por redireccionar archivos.

win_private_assemblies=False. Deshabilita la opción de incluir ensamblados privados cuando se crea un ejecutable para Windows.

cipher= Para utilizar el cifrado que tengamos definido.

Código práctico

Se crea un archivo un archivo comprimido .pyz que incluye los módulos puros de Python.

 

Este bloque define cómo será el ejecutable:

pyz: Es el archivo generado anteriormente.

a.scripts: Contiene el script principal.

exclude_binaries=True: Excluye binarios (los mueve al bundle en COLLECT).

name=’MisContactos’: Nombre del ejecutable final.

debug=False: No se incluye código de depuración.

bootloader_ignore_signals=False: Si es True, ignora señales del sistema.

strip=False: Si es True, elimina símbolos de depuración.

upx=True: intenta comprimir los binarios con UPX (si está instalado).

console=False: No se muestra la ventana de terminal al ejecutar la app.

disable_windowed_traceback=False: Muestra información de traceback en ventanas de error cuando un programa Python termina debido a una excepción no manejada.

argv_emulation=False : Desactiva la emulación de sys.arg

target_arch=None. Significa que no se especifica una arquitectura de destino particular para el ejecutable que se va a crear.

codesign_identity=None: Para firmar la app (dejamos vacío si no se firma).

entitlements_file=None: Para apps firmadas con permisos especiales.

icon=[‘Imagenes/group.icns’]: Icono de la aplicación.

bundle=True: Para generar él .app

 

Este paso agrupa todos los archivos en una carpeta final con formato de aplicación.

exe: El ejecutable que se creó anteriormente.

a.binaries, a.zipfiles, a.datas: Binarios, datos y paquetes comprimidos, creados anteriormente

strip=False: No elimina símbolos de debug (normalmente False en desarrollo).

upx=True: Comprime si es posible.

name=’Mis Contactos’: Nombre de la carpeta final de distribución (y del .app).

 

Aquí se define el .app:

coll: Hace referencia a la agrupación de los archivos que hemos definido anteriormente.

name: Nombre del archivo .app.

icon: Nombre del archivo .icns personalizado.

bundle_identifier: Para notarizar tu app en macOS, formato habitual: ‘com.empresa.nombreapp’.


📘 Entrada publicada por Equipo Python Práctico
¿Tienes dudas o quieres más ejemplos? Visítanos en pythonpractico.com

Publicaciones Similares