taichi
taichi

Reputation: 683

PyInstaller icon option doesn't work on Mac

I ran the following command on my mac and created an .app file.

pyinstaller --icon icon.icns --noconsole -n testApp main.py

However, the generated .app file does not show the icon.

enter image description here

icon.icns is specified as an icon file in info.plist.

enter image description here

The Content/Resouces folder contains icon.icns.

enter image description here

When I run the .app file, I see an icon on the Dock.

However, the icon is not reflected in the .app file itself. Why is this?

Upvotes: 6

Views: 6220

Answers (2)

mellington
mellington

Reputation: 1

A temporary workaround is to simply Get Info on an .icns file in the Finder; click on and copy the image in the top left of the Get Info window; then paste that .icns image into the same location on the Get Info window of your application. You can also copy the .icns image from any existing application to any other application by that method. I believe that functionality has been available on the Mac for well over two decades. Notwithstanding the above, ultimately it should be coded into the Info.plist contents. Edit: the .icns image in the Get Info must NOT show a default image. If it does, then open the .icns image in Preview, copy the image and paste it into any Get Info image you desire. It works for me on my iMac and when copied to two other Macs (Mini 2012 running Mojave 10.14.6 and Mini running El Capitan 10.11.6).

Upvotes: -2

Sederqvist
Sederqvist

Reputation: 2971

You should use the command for creating a macOS app bundle

If specified correctly, the icon.icns will be copied into the Resources folder and applied to the testApp.app bundle in the dist directory, after running the pyinstaller command. (don't try .ico as suggested, that's for Windows).

I just tried creating a simple Python app using PySide2, and it included the icon file in the app bundle with no problems.

Given that the icon.icns is in the same directory as main.py:

Your command should be:

$ pyinstaller --onefile --windowed --icon icon.icns --name testApp main.py

This will produce the app bundle, and you should be able to run it just fine.


But wait, there is even more...

Sadly, the story doesn't quite end here.

SPOILER:

To do things "the right way" and make macOS happy, you should also include the:

--osx-bundle-identifier 'YOUR_IDENTIFIER'

That way the spec file will include the info for the Info.plist file that gets produced.

Also there should be a section in the spec file describing the Info.plist contents, something in the lines of:

app = BUNDLE(exe,
         name='testApp.app',
         icon='icon.icns',
         bundle_identifier='com.youridentifier',
         info_plist={
            'NSPrincipalClass': 'NSApplication',
            'NSAppleScriptEnabled': False,
            'CFBundleDocumentTypes': [
                {
                    'CFBundleTypeName': 'My File Format',
                    'CFBundleTypeIconFile': 'MyFileIcon.icns',
                    'LSItemContentTypes': ['com.example.myformat'],
                    'LSHandlerRank': 'Owner'
                    }
                ]
            },
         )

In the above example, the key/value 'NSPrincipalClass': 'NSApplication' is necessary to allow Mac OS X to render applications using retina resolution.

The key 'NSAppleScriptEnabled' is assigned the Python boolean False, which will be output to Info.plist as <false/>. Finally the key CFBundleDocumentTypes tells Mac OS X what file-types your application supports, if any.

Upvotes: 15

Related Questions