script make icon python pyinstaller

make - python executable windows



Agrupar archivos de datos con PyInstaller(--onefile) (7)

Intento crear un EXE de un archivo con PyInstaller que incluya una imagen y un ícono. No puedo por mi vida hacer que funcione con --onefile .

Si lo hago, --onedir que todo funcione muy bien. Cuando uso --onefile , no puede encontrar los archivos adicionales a los que se hace referencia (al ejecutar el EXE compilado). Encuentra las DLL y todo lo demás bien, simplemente no las dos imágenes.

He buscado en el temp-dir generado al ejecutar el EXE ( /Temp/_MEI95642/ por ejemplo) y los archivos están ahí. Cuando dejo caer el EXE en ese directorio temporal, los encuentra. Muy desconcertante.

Esto es lo que agregué al archivo .spec

a.datas += [(''images/icon.ico'', ''D://[workspace]//App//src//images//icon.ico'', ''DATA''), (''images/loaderani.gif'',''D://[workspace]//App//src//images//loaderani.gif'',''DATA'')]

Debo agregar que he intentado no ponerlos en subcarpetas, no hizo la diferencia.

Editar: Marcó la respuesta más reciente como correcta debido a la actualización de PyInstaller.


En lugar de reescribir todo mi código de ruta como se sugirió, cambié el directorio de trabajo:

if getattr(sys, ''frozen'', False): os.chdir(sys._MEIPASS)

Simplemente agregue esas dos líneas al principio de su código, puede dejar el resto tal como está.


Las respuestas existentes me resultaron confusas y tardé mucho en descubrir dónde está el problema. Aquí hay una compilación de todo lo que encontré.

Cuando ejecuto mi aplicación, foo.py un error. Failed to execute script foo (si foo.py es el archivo principal). Para solucionar este problema, no ejecute PyInstaller con --noconsole (o edite main.spec para cambiar console=False => console=True ). Con esto, ejecuta el ejecutable desde una línea de comandos, y verás el error.

Lo primero que debe verificar es que está empacando sus archivos extra correctamente. Debería agregar tuplas como (''x'', ''x'') si quiere que se incluya la carpeta x .

Después de que se cuelgue, no haga clic en Aceptar. Si está en Windows, puede usar Buscar todo . Busque uno de sus archivos (por ejemplo, sword.png ). Debería encontrar la ruta temporal donde desempaquetó los archivos (por ejemplo, C:/Users/ashes999/AppData/Local/Temp/_MEI157682/images/sword.png ). Puede explorar este directorio y asegurarse de que incluya todo. Si no puede encontrarlo de esta manera, busque algo como main.exe.manifest (Windows) o python35.dll (si está utilizando Python 3.5).

Si el instalador incluye todo, el siguiente problema probable es E / S de archivo: su código de Python está buscando en el directorio del ejecutable, en lugar del directorio temporal, los archivos.

Para solucionarlo, cualquiera de las respuestas sobre esta pregunta funciona. Personalmente, encontré una mezcla de todos ellos para trabajar: cambiar el directorio condicionalmente lo primero en su archivo principal de punto de entrada, y todo lo demás funciona tal como está:

if hasattr(sys, ''_MEIPASS''): os.chdir(sys._MEIPASS)


Las versiones más nuevas de PyInstaller ya no configuran la variable env , por lo que la excelente answer Shish no funcionará. Ahora la ruta se establece como sys._MEIPASS :

def resource_path(relative_path): """ Get absolute path to resource, works for dev and for PyInstaller """ try: # PyInstaller creates a temp folder and stores path in _MEIPASS base_path = sys._MEIPASS except Exception: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path)


Leve modificación a la respuesta aceptada.

def resource_path(relative_path): """ Get absolute path to resource, works for dev and for PyInstaller """ if hasattr(sys, ''_MEIPASS''): return os.path.join(sys._MEIPASS, relative_path) return os.path.join(os.path.abspath("."), relative_path)


Tal vez perdí un paso o hice algo mal, pero los métodos que están arriba no agruparon los archivos de datos con PyInstaller en un archivo exe. Déjame compartir los pasos de lo que he hecho.

  1. paso: escriba uno de los métodos anteriores en su archivo py con la importación de módulos sys y os. Probé a los dos. El último es:

    def resource_path(relative_path): """ Get absolute path to resource, works for dev and for PyInstaller """ base_path = getattr(sys, ''_MEIPASS'', os.path.dirname(os.path.abspath(__file__))) return os.path.join(base_path, relative_path)

  2. paso: escribir, pyi-makespec file.py , en la consola, para crear un archivo file.spec.

  3. paso: Abrir, file.spec con Notepad ++ para agregar los archivos de datos como a continuación:

    a = Analysis([''C://Users//TCK//Desktop//Projeler//Converter-GUI.py''], pathex=[''C://Users//TCK//Desktop//Projeler''], binaries=[], datas=[], hiddenimports=[], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher) #Add the file like the below example a.datas += [(''Converter-GUI.ico'', ''C://Users//TCK//Desktop//Projeler//Converter-GUI.ico'', ''DATA'')] pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, exclude_binaries=True, name=''Converter-GUI'', debug=False, strip=False, upx=True, #Turn the console option False if you don''t want to see the console while executing the program. console=False, #Add an icon to the program. icon=''C://Users//TCK//Desktop//Projeler//Converter-GUI.ico'') coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True, name=''Converter-GUI'')

  4. paso: seguí los pasos anteriores, luego guardé el archivo de especificaciones. Por fin abrí la consola y escribí, pyinstaller file.spec (en mi caso, file = Converter-GUI).

Conclusión: Todavía hay más de un archivo en la carpeta dist.

Nota: estoy usando Python 3.5.

EDITAR: Finalmente funciona con el método de Jonathan Reinhart.

  1. paso: agregue los códigos a continuación a su archivo python con la importación de sys y os.

    def resource_path(relative_path): """ Get absolute path to resource, works for dev and for PyInstaller """ base_path = getattr(sys, ''_MEIPASS'', os.path.dirname(os.path.abspath(__file__))) return os.path.join(base_path, relative_path)

  2. paso: Llame a la función anterior agregando la ruta de su archivo:

    image_path = resource_path("Converter-GUI.ico")

  3. paso: Escribe la variable de arriba que llama a la función hasta donde tus códigos necesitan la ruta. En mi caso es:

    self.window.iconbitmap(image_path)

  4. paso: abra la consola en el mismo directorio de su archivo python, escriba los códigos como a continuación:

    pyinstaller --onefile your_file.py

  5. paso: abra el archivo .spec del archivo python y anexe la matriz a.datas y agregue el icono a la clase exe, que se proporcionó anteriormente antes de la edición en el paso 3.
  6. paso: guardar y salir del archivo de ruta. Vaya a su carpeta que incluye las especificaciones y el archivo py. Abra de nuevo la ventana de la consola y escriba el siguiente comando:

    pyinstaller your_file.spec

Después del 6. paso, su único archivo está listo para usar.


Todas las demás respuestas utilizan el directorio de trabajo actual en el caso en que la aplicación no está PyInstalled (es decir, sys._MEIPASS no está configurado). Eso es incorrecto, ya que le impide ejecutar su aplicación desde un directorio que no sea el de su script.

Una mejor solución:

def resource_path(relative_path): """ Get absolute path to resource, works for dev and for PyInstaller """ base_path = getattr(sys, ''_MEIPASS'', os.path.dirname(os.path.abspath(__file__))) return os.path.join(base_path, relative_path)


pyinstaller descomprime sus datos en una carpeta temporal y almacena esta ruta de directorio en la variable de entorno _MEIPASS2 . Para obtener el directorio _MEIPASS2 en modo empaquetado y usar el directorio local en modo desempaquetado (desarrollo), uso esto:

def resource_path(relative): return os.path.join( os.environ.get( "_MEIPASS2", os.path.abspath(".") ), relative )

Salida:

# in development >>> resource_path("app_icon.ico") "/home/shish/src/my_app/app_icon.ico" # in production >>> resource_path("app_icon.ico") "/tmp/_MEI34121/app_icon.ico"