Python

How to Easily Notarize Python Apps for macOS

A practical guide to signing and notarizing Python apps on macOS, including PyInstaller, py2app, embedded binaries, dylibs, and DMG distribution.

Python apps are often harder to notarize than native macOS apps because they bundle interpreters, dynamic libraries, helper binaries, and framework-like folders.

That does not make Python a bad choice for Mac apps. It just means your release workflow needs to be stricter about signing every executable part of the final bundle.

Build the Python app first

Start with a working .app bundle. Do not try to debug notarization before the app launches correctly on your own Mac.

For PyInstaller, your build command may look like this:

pyinstaller --windowed --name YourApp your_script.py

For py2app, you might use:

python setup.py py2app

Why Python app bundles fail notarization

Python apps commonly include many nested executable files. Apple’s tooling expects every executable binary, dynamic library, and helper component to be signed correctly.

  • Unsigned .dylib files.
  • Embedded Python runtime components.
  • Helper binaries inside package folders.
  • Incorrect executable permissions.
  • Invalid bundle identifiers.
  • Missing hardened runtime.

Inspect the bundle

Before signing, inspect what your build produced.

find "dist/YourApp.app" -type f -perm +111
find "dist/YourApp.app" -name "*.dylib" -o -name "*.so"

The goal is to understand what needs signing instead of assuming one command will handle every edge case.

Sign the app

For many Python apps, a deep signing command is a reasonable starting point, but if notarization fails, sign nested binaries individually and work outward.

codesign --force --deep --options runtime --timestamp \
  --sign "Developer ID Application: Your Name (TEAMID)" \
  "dist/YourApp.app"

Package for notarization

Create a ZIP for the notarization service:

ditto -c -k --keepParent "dist/YourApp.app" "YourApp.zip"

Submit with notarytool:

xcrun notarytool submit "YourApp.zip" \
  --keychain-profile "DMGKit_Notary" \
  --wait

Staple and verify

xcrun stapler staple "dist/YourApp.app"
spctl -a -vvv --type execute "dist/YourApp.app"

If verification fails, go back to the notary log. Python failures are usually specific once you inspect the problematic binary.

Where DMGKit helps

DMGKit helps by turning the final distribution stage into a repeatable release workflow. You still need a valid Python app bundle, but DMGKit helps package, notarize, and present the release as a polished Mac installer.

DMGKit Inspector can also help evaluate whether the resulting installer has the trust signals you expect before you publish it.

Ship cleaner Mac releases

Design, notarize, inspect, and distribute from one native workflow.

DMGKit helps developers turn a fragile release checklist into a polished, repeatable Mac distribution process.

FAQ

Can PyInstaller apps be notarized?

Yes. PyInstaller apps can be notarized, but embedded binaries and dynamic libraries must be signed correctly.

Is --deep always enough?

Not always. It can work for simpler apps, but complex Python bundles may require signing nested components in a controlled order.

Can DMGKit package Python apps?

Yes, as long as the Python build produces a valid macOS app bundle or distributable app structure.

Related guides