skip to Main Content

I’m building a python app which is to pack up as a single executable and work on Windows, MacOS and Linux. Have made a lot of progress and am using a workflow on Github to build using pyinstaller for each OS. Most things are working fine.

Right now I am working on getting an icon onto the executable instead of the default system icon.

I have a spec file for pyinstaller and I have a section where the icon is mentioned:

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.zipfiles,
    a.datas,
    [],
    name='my_app_name',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon='images/my_icon.ico'
)

This seems to work well for Windows and the output exe file has my icon which is great.
My question is, is there a way to do this for Linux. I know that normally for Linux you need to build a .desktop file, so I guess the question is three-fold:

  1. Is there a way to give a file an icon without a desktop file (in Linux)?

or

  1. Is there a way to somehow build and connect a desktop file to my Linux file in pyinstaller?

or

  1. Is there some python way to self-create a desktop file for my python app?

Thanks

2

Answers


  1. Chosen as BEST ANSWER

    OK, so I found a a way to do it - not really in pyinstaller, but it works for me.

    I am building my app(s) using Github's Workflow feature - so we have a file called python_build.yml under /.github/workflows

    So, after building the executable with pyinstaller into a single file I have:

    - name: Assign artifacts
      if: github.event_name == 'release'
      uses: knicknic/[email protected]
      with:
        macos: echo "artifact_path=My_app.dmg" >> $GITHUB_ENV
        windows: echo "artifact_path=dist/my_app.exe" >> $env:GITHUB_ENV
        linux: echo "artifact_path=dist/my_app.deb" >> $GITHUB_ENV
    - name: Create DMG app (for MacOS)
      if: github.event_name == 'release' && runner.os == 'macOS'
      run: |
        rm -rf dist/my_app
        brew install create-dmg
        create-dmg --app-drop-link 100 100 "${{env.artifact_path}}" dist/
    - name: Create DEB file for Ubuntu
      if: github.event_name == 'release' && runner.os == 'linux'
      run: |
        cp dist/my_app my-app/usr/share/bin/my_app 
        rm -rf my-app/usr/share/bin/hold
        fakeroot dpkg-deb --build my-app
    - name: Sleep while DEB build happens
      if: github.event_name == 'release' && runner.os == 'linux'
      run: sleep 30s
      shell: bash
    - name: Copy over DEB to dist folder
      if: github.event_name == 'release' && runner.os == 'linux'
      run: |
        cp my-app.deb dist/my-appi.deb
        rm -rf dist/my_app
    - name: Add artifacts to release
      if: github.event_name == 'release'
      uses: ncipollo/[email protected]
      with:
        allowUpdates: true
        replacesArtifacts: false
        artifacts: ${{env.artifact_path}} 
    

    So, there's a couple of important points to add to this. I have saved in my Git repository a small directory structure named my-app. I don't think this is the web page I used but it's similar. Basically a folder named my-app with two folders underneath it : DEBIAN and usr. In the DEBIAN there is one file called control with something like this in it:

    Package: my-app
    Version: 1.1-7
    Section: Utility
    Priority: optional
    Architecture: i386
    Depends: 
    Homepage: https://www.ourwebsite.com/
    Maintainer: Kibi Hofmann <[email protected]>
    Installed-Size: 31300
    Description: Useful app for your use
     No dependencies or significant conflicts.
     This app is used to do your stuff
    

    Under usr is a folder share which has three more folders under it applications, bin and icons. The bin folder has (in my Git repository) an empty file called hold just so that the directory structure is maintained in Git - you can see that the hold file is deleted and replaced by the compiled binary after pyinstaller is finished. The Desktop file itself is under applications and looks like this:

    [Desktop Entry]
    Type=Application
    Name=My App
    GenericName=My cool app
    Comment=Keep your computer happy
    Exec=/usr/share/bin/my-app
    Icon=myr_icon
    Terminal=false
    Categories=Application
    

    Hope this helps someone!


  2. There’s such a pip library as a auto-py-to-exe. It’s UI for pyinstaller and it makes it quite easier to create exe. Try to apply icon though that stuff.
    I think it also should work for Linux as for Windows. But for me there were some errors if l created few files with same name and different icons. Not sure if it was problem of pyinstaller.

    1. It gives you a possibility to select icon (.ico file). I can guess that your error with icon due to wrong path to file or place from where you run cmd
    2. You can try to write another script that use pyinstaller to do it. But if clearly understood – you can create exe only using this library. If you need shortcut – it can be created by using os.system by another python script.
      Auto-py-to-exe UI
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search