Search code examples
pythonmacosanacondapy2app

How do I use py2app with Anaconda python?


I am using Python 3 from the Anaconda distribution, and trying to convert a simple python program into an OS X app (running on El Capitan). Following the instructions in the tutorial, I ran

py2applet --make-setup my-script.py
python setup.py py2app -A

Everything ran fine with no errors, but when I try to launch the app, I get this error message:

my-script: A python runtime not could (sic) be located. You may need to install a framework build of Python, or edit the PyRuntimeLocations array in this applications Info.plist file.

I understood this to mean I should add the path of Anaconda's python (which is in my bash PATH, but is not known to the launcher). However, the app's automatically generated Info.plist already points to the Anaconda python binary:

<key>PythonInfoDict</key>
<dict>
    <key>PythonExecutable</key>
    <string>/Applications/Experimental/anaconda/bin/python</string>
    ...

I don't see what there is to fix here. I have read these related questions:

The first question involves the same error message, and is resolved by following the advice in the second question. But as I understand it, these questions describe the opposite situation: The OP was running a python distributed with the OS, and wanted to distribute their app; the solution is to use a separately installed python. I am using a non-system python, and I'm not yet trying to distribute anything. So what is causing the trouble here, and what is the solution?


Solution

  • The suggestion by @l'L'l allowed me to identify the problem: While there were no errors when I generated my app in "alias mode" (using symlinks to the environment instead of copying binaries), building the app without alias mode flushed out the error: py2app looks for the libpython DLL under the non-existent name /Applications/anaconda/lib/libpython3.4.dylib.

    A quick check showed that Anaconda provides this DLL under a slightly different name: libpython3.4m.dylib. While patching dist/my-script.app/Contents/Info.plist fixes the problem, the right solution is to edit setup.py so that future builds will work correctly. With the help of the py2app documentation, I put together the following (partial contents of setup.py shown):

    OPTIONS = {'argv_emulation': True,
               'plist': {
                   'PyRuntimeLocations': [
                    '@executable_path/../Frameworks/libpython3.4m.dylib',
                    '/Applications/anaconda/lib/libpython3.4m.dylib'
                   ]
               }}
    
    setup(
        app=APP,
        data_files=DATA_FILES,
        options={'py2app': OPTIONS},
        setup_requires=['py2app'],
    )
    

    The paths come from the generated Info.plist; I only modified the absolute path, reasoning that if I ever provide a local DLL at the relative path, it will have the default name.