How do I use py2app with Anaconda python?
Asked Answered
L

1

5

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?

Lockard answered 7/9, 2016 at 21:19 Comment(2)
Have you tried running the app without using the alias option (eg. python setup.py py2app), or by open -a dist/MyApplication.app?Alwin
Useful suggestion! open -a dist/my-script.app fails ("Unable to find application named 'dist/my-open.app'"), but trying a full app build (still doesn't work but) flushed out the problem: The libpython dll is not named as py2app expects. I was able to fix it by editing the generated Info.plist.Lockard
L
10

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.

Lockard answered 8/9, 2016 at 13:25 Comment(9)
How did you find both of those DLLs? I have the same problem, and tried including the one DLL I could find in the PyRuntimeLocations: /Users/***/anaconda/lib/libpython3.5m.dylib. It doesn't seem to make a difference, though. In fact, I tried including /Users/***/anaconda/lib/nonsense.dylib and nothing changed, no error was thrown.Overzealous
I just cd'd to the directory that would have contained the file py2app tried to include, and checked what else is there. But you could also try mdfind -name libpython (if you're on OS X; otherwise it's locate or slocate, I guess). But you're saying you didn't actually see the error I describe in my answer? Did you try building in non-alias mode? If you did and you're not getting the error message, you probably have a different problem.Lockard
To clarify: I get the same error that you got, and am building in non-alias mode. py2app also gives this error message while compiling: ValueError: '/Users/***/anaconda/lib/libpython3.5.dylib' does not exist But py2app gives me that same error no matter what I put in 'plist', i.e.: {'PyRuntimeLocations': ['/Users/****/anaconda/lib/nonsense.dylib']}. And then gives me the "edit the PyRuntimeLocations" error when I try to open it. So it doesn't seem like it is actually using the PyRuntimeLocations. I was wondering how you got PyRuntimeLocations to actually work.Overzealous
I got it to work by putting in the path to a DLL that does actually exist. If you edit setup.py, you need to rerun py2app (i.e. python setup.py py2app).Lockard
You must be confused about something, because of course writing a nonsense name will give you the same error as the file inserted automatically: Neither file exists. And in your first comment you say "nothing changed, no error was thrown"... so not sure what you're actually doing. Double- and triple-check that you provided the library name correctly. (Example only: Maybe there's an accent in your user name, opening the door to encoding issues?) Anyway I only saw the error when I tried to open the app with open -a, not at build time.Lockard
When I try this solution, I edited my setup.py to include my anaconda3 version of libpython3.6m.dylib but it continues to give me the starting error message: "ValueError: '/anaconda3/lib/libpython3.6.dylib' does not exist" What did you do to know setup.py's path was being executed.Surpassing
I can't say I remember, exactly; I looked at the py2app documentation and studied the generated setup.py. I knew it was being read when either the symptoms or the error message changed. (By the way the link to the documentation in my answer was stale; if you didn't bother to find the right doc yet, try again.)Lockard
PS You did re-run python setup.py py2app after you edited setup.py, right? ...Lockard
Yup! It wouldn't get through execution anyway, so I would need to in order to have something to try to run. I added a symbolic link between libpython3.6m and libpython3.6 and got the setup to complete, but now I still have the "fatal termination no python" error when I try to click the app.Surpassing

© 2022 - 2024 — McMap. All rights reserved.