Setting Mac OSX Application Menu menu bar item to other than "Python" in my python Qt application

You seem to need an OSX .app for this to work, as the Info.plist file in there contains the user-visible name for the application that is put there. This defaults to Python, which is the title you see for the program menu. This blog post outlines the steps you need to take, while the OSX Developer Library has the docs on the property list you need to fill.


I have found the kernel of an answer to this question. Because I want to award the bounty to someone other than myself (I am the OP), please, anyone, take this kernel and elaborate it into a more complete answer of your own.

I can get the application menu to be "MyApp" as follows:

ln -s /System/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python MyApp

./MyApp MyApp.py

There are two elements required to get this to work:

  1. The symbolic link must be named "MyApp" (or whatever you want to appear in the Application Menu)
  2. The symbolic link must point to the Python executable inside the system python app bundle. It does not work if you link to /usr/bin/python, for example.

There must be a clever way to create an app bundle or shell script that exploits this mechanism in a robust way...


If you intend to distribute the app, then symlinking the python binary is not guaranteed to work, considering that typically on development machines the system python is not the default python, and regular users most likely won't have Qt and PyQt installed.

A more reliable approach is to have a native OSX bootstrapping binary that would take care of starting your PyQt app. Both py2app and PyInstaller can generate native wrappers. While py2app worked well for creating an aliased app, i.e. a wrapper that symlinks to existing files on your system, getting it to bundle only the required PyQt dependencies proved to be non-trivial. Moreover the 'aliased app' generated by py2app with the --aliased flag will stop working if you move it to another folder since the symlinks are relative to the folder where you originally ran the build script.

PyInstaller

PyInstaller worked out-of-the-box and I ended up with an OSX bundle that included the dependencies all at around 16MB.

Bundle a python script to a standalone OSX app:

pyinstaller -w --noconfirm -i=myappicon.icns --clean -F myscript.py

This generates a standalone bundle that will display whatever you have in your .setWindowTitle() as the app name in the OSX title bar. The -w switch is important as it will create a MacOS app bundle with a proper .plist file.

NB: For some reason, the version of pyinstaller installed via pip did not work for me. So I removed the original pip version (pip uninstall pyinstaller), and installed the latest develop branch from github with:

pip install -v -e git+https://github.com/pyinstaller/pyinstaller.git@develop#egg=pyinstaller-github

After that it worked like a charm.

Mac Automator

Yet another option to create an app wrapper is to use Automator (type the name in Spotlight), go to File > New > Application > search for and drag Run shell script into the editor and under Shell select bash, python. You can also use the Run Applescript and bootstrap your app using apple script - can be useful if you need, for example, to ask the user's password in order to run with elevated privileges.

A better alternative to Automator is Platypus - a free and open-source app that wraps various types of scripts into OSX apps, and also provides some extra features like gui text output windows, running with admin privileges, setting custom icons, etc. The code is available on github.

There is also the option to create a barebones OSX app in Xcode that will launch your PyQt script (some examples here), and do other custom tasks required by your app.

NOTE: Keep in mind that an app bundle that calls your python code with a predefined interpreter is a 'shallow' app bundle, and will depend on whatever python dependencies you have install locally. Most likely will not work OOTB on someone else's Mac.

Nuitka

You might also want to try Nuitka (pip3 install nuitka) which aims to be a project to build truly native executables by converting your python code to C++ and then compiling it.

An example of building a native app with nuitka:

nuitka3 --follow-imports --python-flag=no_site --verbose --standalone --show-progress --show-modules --output-dir=my_build_dir myscript.py

This will create the mac executable with libraries in the my_build_dir folder. You will need to wrap them yourself in a MacOS app bundle, for example with Platypus or with Automator.


I know this isn't what the OP wants exactly, but figured it could add some value to searching for a solution to this issue.

You can make the file menus appear in your window UI instead of in the native Mac OS X system menubar:

menubar.setNativeMenuBar(False)

This will cause the menubar to appear as it would appear in e.g. Windows.