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

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:
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:
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:
Y cambiar el código del método cambiar_idioma por:
8.- En PantallaSplash.py modificar en el método __init__ la asignación de la imagen.
9.- En PantallaTelefonos.py cambiar la asignación de iconos a los botones por:
10.- En Principal.py en el método open_main_window, añadimos la línea 46 para mantener la referencia.
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:
12.- En Mensajes.py modificar el método __init__ de la clase MiMessageBox para cambiar la asignación del icono de la siguiente manera:
13.- Crear archivo build.spec para generar el archivo .app con el código siguiente:
14.- Ejecutar desde el terminal el siguiente comando:
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:
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.
Y en el método open_main_window añadiremos la línea 47.
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.
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:
Explicación archivo .spec
Explicación del archivo build.spec
Esto indica que el archivo es Python y usa codificación UTF-8.
Utilizaremos block_cipher para cifrar archivos con clave si se usan contraseñas. En nuestro caso, está desactivado.
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.
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