Sandboxing MacOS app built in Python causes import error for os module

iHi guys,


I have a MacOS app built in Python that I would like to submit to the Mac App Store. Apple documentation claims that I must code sign my app with the Sandbox entitlement in order to qualify the app for the App Store. However, sandboxing the app causes it to break, and I believe it is because:



1. My app is using Python's built-in "os" module to read and get the paths of files

2. My app is using Python's built-in "sys" module to check the operating system



To give you more context, the app is built using py2app and works just fine until it is sandboxed. I don't want to release it as .pkg or .dmg because of a host of other issues with Apple's notarization process. Here is the error I am getting when running the executable file in my bundle after codesigning with the sandbox entitlement:


Traceback (most recent call last):
  File "site.pyo", line 22, in <module>
    (
ImportError: No module named os
logout
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.


I'm certain it is because 'os' is outside of my sandbox container. This is all just my best guess after a lot of digging, but I could be wrong.

I read that com.apple.security.temporary-exception is a potential fix, but it is not acceptable for release in the Apple Store. Please help as I am running out of ideas. Are there any solutions to this problem or do I just have to accept that my app cannot be released to the Apple Store?

Post not yet marked as solved Up vote post of qche Down vote post of qche
1.8k views

Replies

Does

py2app
add a copy of the Python runtime to your app? Or are you expecting to use the system’s built-in Python runtime?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I am not 100% certain, but it appears from my Info.plist that py2app is trying to use a copy but that copy is not in the Framework. That part seems a little unclear to me but this is my Info.plist and some observations:


...
<key>PyRuntimeLocations</key>
     <array>
          <string>@executable_path/../Frameworks/Python.framework/Versions/2.7/Python</string>
          <string>/System/Library/Frameworks/Python.framework/Versions/2.7/Python</string>
     </array>
<key>PythonInfoDict</key>

<dict>
<key>PythonExecutable</key>
<string>/Users/andrew/virtualenv/slugGameEnv/bin/python</string>
....


Two potential issues that I see here:

- @executable_path/../Frameworks (Item 0) does not contain the Python.framework, making me assume that the Python runtime was NOT copied over by py2app and it's falling back to the system's Python at /System/Library/Frameworks/Python.framework... (Item 1)

- The python executable that is in MyApp.app/Contents/MacOS/ is a symlink (possible issue?)

In theory, this is possible. You could build your own python from source and install into a custom prefix. Use py2app to export your app. Then, add whatever parts of your python that you need into your app. And if you're really lucky, you'll have some way of bootstrapping all of this with something to identify where your copy of Python lives inside your app bundle. You should expect similar signing and upload hassles with the Mac App Store that you are worried about with notarization.


You might find it easier to just re-write the thing in Swift.

Two things:

  • What’s the deal with

    PythonExecutable
    ? The sandbox won’t allow access to the user’s home directory. Even if it did, that item is not going to be present on other systems.
  • I think you need to make an active decision as to whether to bundle the Python runtime or not. There are some tricky trade-offs here

    • Bundling the runtime makes your app bigger.

    • It also complicates your code signing story.

    • Apple has officially deprecated our built-in scripting language runtimes. See the discuss in the macOS Catalina 10.15 Release Notes. Now, I don’t image we’ll be removing them any time soon — that’d break a lot of stuff — but it could complicate your future. If, for example, we made an architecture transition [1], like the 32- to 64-bit transition we’ve just completed, it’s not hard to imagine the built-in scripting language runtimes being unavailable in the new architecture.

    • The built-in scripting language runtimes are kinda frozen in amber. If you bundle your own runtime, you get more control. For example, Python 2.x is now officially unsupported, and I personally wouldn’t ship new software based on it.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] No, this isn’t a product announcement, it’s just that architecture transitions are a fact of life on Apple platforms. Depending on how you count them, I’ve lived through about seven (32-bit clean, PowerPC, Mac OS X, 64-bit x 3 (on PowerPC, Intel, and Arm), Intel, iOS, Arm).