Python For Macos Catalina

Posted on  by 

Question or issue on macOS:

I am developping a simple Python application using a PySide2 GUI. It currently works fine in Windows, Linux and Mac. On Windows, I could use PyInstaller and InnoSetup to build a simple installer. Then I tried to do the same thing on Mac. It soon broke, because the system refused to start the command or the app generated by PyInstaller because it was not correctly signed. And as I am not an apple developper, I cannot sign anything…

Question or issue on macOS: I am developping a simple Python application using a PySide2 GUI. It currently works fine in Windows, Linux and Mac. On Windows, I could use PyInstaller and InnoSetup to build a simple installer. Then I tried to do the same thing on Mac. It soon broke, because the system refused. : $ python WARNING: Python 2.7 is not recommended. This version is included in macOS for compatibility with legacy software. Future versions of macOS will not include Python 2.7. Instead, it is recommended that you transition to using 'python3' from within Terminal.

This article will help you to set up a Python virtual environment on Mac OS or your Macbook.If you are a Mac user, you should know that Python 2.7.x comes pre-installed in your Macbook, but as that is required by your operating system, so you cannot modify it or update it and I would recommend that you don't use it at all. MacOS Catalina (released in 2019) still does not have Python 3 installed by default, only Python 2. Therefore, I needed a way to package the whole application into an app bundle and not make it dependent on user’s Python installation. There are several tools that help with that: py2app, briefcase, pyinstaller. I decided to use PyInstaller, it.

After some research, I tried py2app. I can go one step further here. With

I can create a runnable app. Which obviously cannot be ported to a different system because it uses my development folders. And if I use python setup.py py2app the generated program cannot start because py2app did not copy all the required Qt stuff. I tried to add one by one the missing libraries, but on the end the system could not find the plugins and I gave up…

Can someone help me with a recipe to convert a python script or package using a Qt GUI into a portable app on Mac? Ideally, the recipe should say how to use a custom application icon, but this is not required.

As my real package is too large for a SO question I trimmed it down to a minimal reproducible example:

And here is the setup.py file used for py2app:

How to solve this problem?

Solution no. 1:

Requirements

  • works with Python 3.8.5
  • macOS 10.15.7 Catalina
  • uses PySide2 and py2app

Problems

  • PySide2 must be added under OPTIONS to the packages list
  • when running the app then still an error occurs: Library not loaded: @rpath/libshiboken2.abi3.5.15.dylib, Reason: image not found

Solution

The slightly modified setup.py could look like this:

Additionally, an icon definition and a few plist entries for some basic information have been added.

The whole build is best triggered with a script that could look like this:

Test

Here the screenshot of a test run:

Solution no. 2:

I think what you’re missing is the inclusion of the Python3 Framework in your application bundle. I’ve developed a simple macOS app myself recently, however I wanted to have a little more insight on how to do so, so I did a bit of digging into the actual structure of an application. Basically, you are going to put everything into a normal folder with the name of your application. Call this folder MyApp. Inside this folder we’ll have another called Contents. From my understanding, py2app just takes all of the things that make up your app, and structures them inside of this folder as well as creates an Info.plist file, which also goes inside of Contents. So far, here is what you have:

MyApp

Python

-> Contents

-> -> Info.plist

In addition to the Info.plist file with all of the necessary properties, in your Contents folder you will have a MacOS folder and a Resources folder at minimum. Your issue is that you also need a Frameworks folder, where you would add the required version of Python.

Now, your app hierarchy should look like:

MyApp

-> Contents

-> -> Info.plist

-> -> MacOS

-> -> Resources

-> -> Frameworks

In the Frameworks folder, you can put the full Python 3 framework you’re working with to build the app, as well as any site-packages that you require to run the application, and then you can reflect all of those changes in the executable so that you are pointing to the correct installations.

To my understanding, all that’s necessary to make the application functional on MacOS is to ensure that your main executable is placed in the MacOS folder and points to the Python located in your Frameworks folder, your icon .icns file is placed in the Resources folder, and your Info.plist file is built.

In order for MacOS to recognize it as a full application, I believe you possibly need to use productbuild and include a Developer license certificate, but it’s really only necessary if you want the application to be distributed. Otherwise, I just added the extension .app to MyApp, which converts it into an application.

Without the above-mentioned license/certificate whatever, it probably won’t recognize that it should find your icon file and add it, so if you open it in Preview, select-all, and copy it, you should be able to right-click on the application, press ‘Get Info’, and paste the icon on top of the current icon in the window to make it display correctly.

EDIT: My resources for learning about making macOS apps:

Solution no. 3:

I have successfully build apps using fbs.
It is intended to build Python+PyQt5 apps (you can also use PySide2) and it should work on Mac OS as well (according to the documentation/tutorial).

Using PyInstaller it failed very often for including PyQt5 dependencies (especially when I was working with pyqtgraph), but with fbs it works great.

Solution no. 4:

I think the solution to your problem can be found here. First, create a virtual environment and install all modules to the same virtual environment.

Install Qt framework

Then, install the PySide2

After that,

Build, and install PySide2 and make sure to set the path of QMAKE that comes with the Qt installation

Update

First, make sure that you run your code in the same virtual environment, and to convert it to a standard mac OS app you can use py2app or pyinstaller . Also, try to downgrade your py2app if it is not working with your current version after you follow the same process.

Create setup.py

and you have to create a config file or see this example and include any file that you have

To build the application use

To run the app you have to use this way

If it is work with python setup.py py2app -A that means that everything is going ok and you need to use

If any things go wrongs please refer to these references1, 2, and 3. Also, there are alternatives ways to convert your app to os.

After I read your comment, I tried to see what is the problem and I found this and it may solve the problem or you can use alternatives tools such as bbFreeze, pyInstaller or cx_Freeze

Python ide mac os catalina

Solution no. 5:

If you want to package for OSX, you should either

Create a Brew Tap

This probably makes the most sense for an open source developer

General Instructions https://docs.brew.sh/How-to-Create-and-Maintain-a-Tap

  • host your code in git (does not need to be GitHub)
  • create a Formula (Formula Cookbook)
  • fork homebrew-core on GitHub
  • add your Formula and create a pull request to get it into the main repo
  • support your pull request such that it is completed
Join the Apple Developer Program

This probably makes the most sense for a closed source developer

Overview: https://developer.apple.com/programs/how-it-works/

This program costs 99USD annually, but will allow you to sign your package/final binary and distribute it yourself or on their App Store

After creating your account, here’s a guide for packaging and signing for OSX https://developer.apple.com/forums/thread/128166

  • structure your code to support signing (add a build step to copy your work into a clean path to avoid frustrating rework)
  • % codesign -s <Developer ID Application signing identity> /path/to/code
  • pick a storage format (.zip, .dmg, .pkg) and bundle your application as it

Hope this helps!

Python has an amazingly rich ecosystem of libraries, tools and frameworks. It is a clean, modern language, it allowsfor rapid prototyping and quick development cycles. UI was not the central, focal point of my app, so it made a lotof sense for me to do it in Python: I thought I’d write the core functionality first, and add the UI afterwards.

MacOS Catalina (released in 2019) still does not have Python 3 installed by default, only Python 2. Therefore, I neededa way to package the whole application into an app bundle and not make it dependent on user’s Python installation.There are several tools that help with that: py2app,briefcase, pyinstaller. I decided to usePyInstaller, it’s mature, flexible, and offers more customization than the other options.

Step 1: PyInstaller spec file

PyInstaller can be driven by command-line options alone, but that works well for the simplest cases only, and packagingany non-trivial app is not one of these. I suggest running it with command-line parameters, which creates the spec filewith the default values, and then modifying the spec file to suit your needs better. For example, to set the bundleversion to the same value as the application version, and to add some custom plist values:

Step 2: Build the App

This is as simple as

My Application.app will be created, which you can (and should) test to make sure it actually works. Some Pythonpackages require tweaks in PyInstaller spec file: including extra data files in the bundle, etc.

Step 3: Sign the App

In order to be able to notarize it, you must use the hardened run-time.The Hardened Runtime doesn’t affect the operation of most apps, but it does disallow certain capabilities. For Pythonapplications specifically, we need to allow unsigned executable memory. If your app relies on any other capabilitythat the Hardened Runtime restricts, add an entitlement to disable that individual protection as well.

Add entitlements.plist to your project’s root:

And now we’re ready to sign:

Note that in order to be able to notarize the app, you need to sign it with your Apple Developer IDcertificate. Adjust the “Developer” above to match your certificate name, if needed.

Apple recommends to not “deep-sign”, but in this case it’s actually required as all the bundled Python libraries doneed to be signed, not just your main binary.

By adding the --timestamp parameter we include a secure timestamp with the code-signing signature. This is arequirement for notarization.

By adding the entitlements file and passing a -o runtime parameter we enable the hardened runtime, which is alsoa requirement for notarization.

Step 3: Notarize the App

In order to be able to notarize the app,you need to satisfy some additional requirements:

Python os x catalina
  • All the binaries in the application must be linked against macOS 10.9 or later SDK. If you just re-built everythingwith a recent Xcode, this requirement would be satisfied. If, however, you’re packaging some Python dependency witha pre-built binary extension, it might be built against an older SDK. In this case, you’ll need to build this specificpackage from source.

  • Do not include entitlements that are specifically prohibited. At the time of this writing it’s just onecom.apple.security.get-task-allow entitlement.

Store Apple credentials in the keychain

In order to notarize the app, altool must be able to access Apple APIs on your behalf. To secure this access,store your Apple account credentials in the keychain:

Notarize it!

Since altool expects a Zip archive and not a bare .app directory, create a Zip file first and then notarize it:.

Now you need to wait for the notarization results. You’ll get an email from Apple once it’s complete, stating eithera success or failure (and linking to the error logs in this case).

Step 4: Staple the App

In the notarization step above, Apple has created a “ticket”, which is basically a database record which matches yourapp’s signature and saying that it’s been notarized. Your binary has not been modified in any way. When MacOS runsthis app, it will contact Apple servers and ask for a ticket. If such a ticket exists, the app is deemed “notarized”This will happen only once, and then MacOS will cache the results.

If we want to speed up this initial application execution, or if we want to be able to run it when offline, we need to“staple this ticket to the app”, which downloads the ticket and attaches it to your binary. This is as simple as:

This step is optional, but it must be run only after you received an email from Apple stating that the notarizationwas successful.

Step 5: Verify

Now is the good time to verify that everything is in order:

This command uses Gatekeeper directly to assess whether the application is correctly signed and notarized. It shouldreport:

Conclusion

While the process outlined above works today, it is certainly cumbersome and has some downsides:

Python version macos catalina

Python Version Macos Catalina

  • The development and build process is much more complicated than the normal MacOS development process with Xcode.Getting new developers onboard would be tricky.

  • It is hard to control the libraries that are being pulled in into your app. If some of the dependencies were builtwith Homebrew, the application probably won’t work on MacOS versions older than the build machine.

Python Os X Catalina

In my opinion, writing MacOS applications in Python is an acceptable route for prototyping, or for building simplein-house tools quickly, and even notarizing the app is perfectly doable.

Coments are closed