Unable to create functional app bundle on Sierra using py2app and python 3.6.2

615 views Asked by At

I'm using python 3.6.2 with pyenv and homebrew on Mac OS Sierra and i've been unable to create functional bundle apps with py2app v0.14 and pyinstaller v3.2.1.

ActiveTcl version 8.5.18/tkinter are installed.

Standard 2.7.10 Mac version of python doesn't do much else. I actually managed to make one or two attempts to work on python 2.7.10 with other programs, but since i want to use 3.6.2 there's no point to stay on standard.

py2app creates an .app file that just gives "error" and Mac asks to terminate. pyinstaller doesn't even create an .app file. I followed all the instructions in all the programs.

py2app gives me this message at the end when creating the .app:

Modules not found (unconditional imports):

 * com (com.sun.jna)
 * com.jna (com.sun)
 * com.sun (com.sun.jna.platform)
 * ordereddict (pkg_resources._vendor.pyparsing)
 * win32com (win32com)
 * win32com.shell (win32com.shell)
 * win32com.shellcon (win32com.shell)

Modules not found (conditional imports):

 * StringIO (pkg_resources._vendor.six)
 * com (pkg_resources._vendor.appdirs)
 * com.sun.jna (pkg_resources._vendor.appdirs)
 * com.sun.jna.platform (pkg_resources._vendor.appdirs)
 * win32com (pkg_resources._vendor.appdirs)
 * win32com.shell (pkg_resources._vendor.appdirs)

I checked for missing modules and for me it doesn't look like the program is trying to use any module listed above.

I retrieved the program from the internet, it's a simple test program, here's the script:

from tkinter import *
from tkinter import ttk

def calculate(*args):
    try:
        value = float(feet.get())
        meters.set((0.3048 * value * 10000.0 + 0.5)/10000.0)
    except ValueError:
        pass

root = Tk()
root.title("Feet to Meters")

mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)

feet = StringVar()
meters = StringVar()

feet_entry = ttk.Entry(mainframe, width=7, textvariable=feet)
feet_entry.grid(column=2, row=1, sticky=(W, E))

ttk.Label(mainframe, textvariable=meters).grid(column=2, row=2, sticky=(W, E))
ttk.Button(mainframe, text="Calculate", command=calculate).grid(column=3, row=3, sticky=W)

ttk.Label(mainframe, text="feet").grid(column=3, row=1, sticky=W)
ttk.Label(mainframe, text="is equivalent to").grid(column=1, row=2, sticky=E)
ttk.Label(mainframe, text="meters").grid(column=3, row=2, sticky=W)

for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)

feet_entry.focus()
root.bind('<Return>', calculate)

root.mainloop()

I've tried uninstalling and reinstalling python, ActiveTcl, i've run brew doctor, nothing seems to work. Pyenv is working fine. Homebrew is working fine.

I've searched everywhere for two days, and no matter what i do every time py2app creates the .app file it only gives "Error".

The app runs perfectly when i run through IDLE. What problem can it be???

EDIT: After sometime working this out i found a solution for python 3.6.2 using cx_freeze. Py2app only worked with Python 2.7.10 as i told before. For some reason Py2app only load the missing modules i mentioned earlier when running with python 2.7.10, when python 3.6.2 comes in he fails to load the modules and the .app file don't work properly.

1

There are 1 answers

0
chmedly On

After my own 'pyjinks' with py2app I found a few things that might relate.

First of all, your problem with 'error' sounds like an issue that I experienced when my app file was sync'd (via a dropbox style service) to another computer. The file would run fine on the computer that created it but I would get an error that it couldn't be opened when I tried to run it on the remote computer. BUT, if I uploaded the app file via google drive and then downloaded it to the remote computer, it would open and run fine!! So, after poking around I found that the python script inside the app bundle on this remote computer didn't have execution permissions. After running 'chmod 775 myapp.py' on the script, MacOs would open it.

I ran across this same gotcha with an app using pydub and ffmpeg that had to do with the fact that pydub uses subprocess to run ffmpeg. If ffmpeg is in your system's path then pydub finds it ok but if you're packaging your app with py2app, then it's a different story because the ffmpeg that comes in the app won't be in the system path [of this other computer]. I ended up using this line in my python app to define where the ffmpeg is: btw, AudioSegment is a module of pydub and the converter attribute tells it to look for it's format conversion tool at this specific path:

AudioSegment.converter = "../Frameworks/ffmpeg"

Then I put this in the py2app setup file:

OPTIONS = {
    'frameworks': ['/usr/local/Cellar/portaudio/19.6.0/lib/libportaudio.dylib',
    '/usr/local/Cellar/ffmpeg/3.4/bin/ffmpeg'], }

This tells py2app to add the [portaudio and] ffmpeg Framework to the bundle. BUT, I found that the file named ffmpeg that is included doesn't have execution privileges out of the gate. After each py2app creation I had to 'chmod 775 ffmpeg' inside the contents of the app 'bungle' in order to allow the app to run ffmpeg.
I'm not sure if there are special rules with py2app that allow it to create files with execution permissions but it didn't do it automatically.

While troubleshooting this kind of thing it can be difficult to get info about what's going wrong where. So I looked for extra techniques to find what was going wrong. It might be a good idea when troubleshooting a py2app issue to use a lot of try's so you don't miss any exceptions:

try:
    from tkinter import *
except Exception as e:
    print("tkinter didn't import: {}".format(e))