Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

how to run a Framework build of python (and can that requirement be added to the installation instructions?) #259

Open
mroswell opened this issue Feb 18, 2018 · 17 comments

Comments

@mroswell
Copy link

  • [x ] OS - Mac
  • [ x] Python Version - Python 2.7.14 :: Anaconda, Inc.

I saw the message about needing a Windows framework (which wasn't mentioned in the installation instructions)

$ python example_progress_bar_1.py
This program needs access to the screen.
Please run with a Framework build of python, and only when you are
logged in on the main display of your Mac.

figured out that I could do this

conda install python.app

Here's what I get when I try to run pythonw on the simple_demo.py in the example files

$ pythonw simple_demo.py
Traceback (most recent call last):
  File "simple_demo.py", line 28, in <module>
    main()
  File "/Users/mr/anaconda2/lib/python2.7/site-packages/Gooey-1.0.0-py2.7.egg/gooey/python_bindings/gooey_decorator.py", line 83, in inner2
    return payload(*args, **kwargs)
  File "simple_demo.py", line 24, in main
    args = parser.parse_args()
  File "/Users/mr/anaconda2/lib/python2.7/site-packages/Gooey-1.0.0-py2.7.egg/gooey/python_bindings/gooey_parser.py", line 113, in parse_args
    return self.parser.parse_args(args, namespace)
  File "/Users/mr/anaconda2/lib/python2.7/site-packages/Gooey-1.0.0-py2.7.egg/gooey/python_bindings/gooey_decorator.py", line 78, in run_gooey
    application.run(build_spec)
  File "/Users/mr/anaconda2/lib/python2.7/site-packages/Gooey-1.0.0-py2.7.egg/gooey/gui/application.py", line 15, in run
    app = build_app(build_spec)
  File "/Users/marjorieroswell/anaconda2/lib/python2.7/site-packages/Gooey-1.0.0-py2.7.egg/gooey/gui/application.py", line 24, in build_app
    gapp = GooeyApplication(merge(build_spec, imagesPaths))
  File "/Users/mr/anaconda2/lib/python2.7/site-packages/Gooey-1.0.0-py2.7.egg/gooey/gui/containers/application.py", line 39, in __init__
    self.header = FrameHeader(self, buildSpec)
  File "/Users/mr/anaconda2/lib/python2.7/site-packages/Gooey-1.0.0-py2.7.egg/gooey/gui/components/header.py", line 33, in __init__
    self.layoutComponent()
  File "/Users/mr/anaconda2/lib/python2.7/site-packages/Gooey-1.0.0-py2.7.egg/gooey/gui/components/header.py", line 60, in layoutComponent
    self.settings_img = self._load_image(images['configIcon'], targetHeight)
  File "/Users/mr/anaconda2/lib/python2.7/site-packages/Gooey-1.0.0-py2.7.egg/gooey/gui/components/header.py", line 92, in _load_image
    return imageutil.wrapBitmap(sizedImage, self)
  File "/Users/mr/anaconda2/lib/python2.7/site-packages/Gooey-1.0.0-py2.7.egg/gooey/gui/imageutil.py", line 23, in wrapBitmap
    bitmapData = wx.Bitmap.FromBufferRGBA(im.size[0], im.size[1], im.convert('RGBA').tobytes())
AttributeError: type object 'Bitmap' has no attribute 'FromBufferRGBA' 

I guess pythonw isn't the right thing to run a Framework build of python.
Maybe this has something to do with wxPython, but

$ wxPython simple_demo.py

doesn't work...
What should I be doing to run a Framework build of python?

@smoltis
Copy link

smoltis commented Apr 3, 2018

In Anaconda distribution you can use "pythonw" instead. It will use Framework version of python. Like so,

pythonw simple_demo.py

@chriskiehl
Copy link
Owner

Related duplicate issue: #348

@engdan77 have you tried following the OSX instructions in the PyInstaller FAQ for dealing with screen issues?

It suggests building with the --windowed option.

Created binary does not work on Mac OS X and I get message like
This program needs access to the screen. Please run with 'pythonw', not 'python', and only when you are logged in on the main display of your Mac.
This happens when you develop a GUI application for Mac. For GUI applications you need to use the precompiled bootloader linked with graphical Mac OS Xlibraries. You could do that with option --windowed.

@engdan77
Copy link

In Anaconda distribution you can use "pythonw" instead. It will use Framework version of python. Like so,

pythonw simple_demo.py

In Anaconda distribution you can use "pythonw" instead. It will use Framework version of python. Like so,

pythonw simple_demo.py

I tested this and worked for me, even though I have challenges get PyInstaller to use a workable package "windowed" described in #348 ...

@engdan77
Copy link

Related duplicate issue: #348

@engdan77 have you tried following the OSX instructions in the PyInstaller FAQ for dealing with screen issues?

It suggests building with the --windowed option.

Created binary does not work on Mac OS X and I get message like
This program needs access to the screen. Please run with 'pythonw', not 'python', and only when you are logged in on the main display of your Mac.
This happens when you develop a GUI application for Mac. For GUI applications you need to use the precompiled bootloader linked with graphical Mac OS Xlibraries. You could do that with option --windowed.

(I now noticed #348 was closed to pasting the answer here instead)

Thank you @chriskiehl for such fast feedback, it was indeed a good resource reading "PyInstaller FAQ" that very closely relates to the same symptom that I've been seeing. Even though as I've been generating this "freezed" version by using as below this on a Macbook only while using built-in display it gives this error.

python3 -m PyInstaller -F --windowed widget_demo.spec

What makes me wonder is that if I follow the exact same steps but instead in a folder create an wx_test.py with the following code

import wx
class Frame(wx.Frame):
    def __init__(self, title):
        wx.Frame.__init__(self, None, title=title, size=(350,200))
app = wx.App(redirect=True)
top = Frame("Hello World")
top.Show()
app.MainLoop()

It'll generate a package that you could run either as "dist/wx_test" or "open dist/wx_test.app" and this works without any warnings or issues. While doing the same but instead using widget_demo.py together with this widget_demo.spec (this needed to include e.g. images + languages) it would give this "This program needs access to the screen".

Also, obviously there is no issues with neither widget_demo.py (proven when running by "python3 ./widget_demo.py" works perfectly fine), nor PyInstaller since that works perfectly find when packaging wx_test.py. And my understanding was that Gooey uses wx as framework so can't wrap my head around why it would work with this simplified wx_test.py but not widget_demo.py ..

But it is correct that while I was also (one of the many approaches) originally used pyenv I learned that you had to install the python-interpreter using this "--include-framework" and also tested anaconda which I also learned that if you wanted to run widget_demo.py you had to to use pythonw instead that I think must have answered @mrosewell issue he had.

I am very impressed by the simplicity of Gooey and also that it looks that good so I would be happy to do what I can to help "triage" this. I've spent a couple of days searching internet for others in the same spot which I would not find that unlikely - but the few I've seen are quite old and been using Python2 .. that is why I also now tested the same from another Mac OS 10.13 (High Sierra) using older Python 3.5.4 (installed from Mac binaries from www.python.org) in the hope of that it would make a difference but unfortunately not.

Thanks again ...

@aatwork
Copy link

aatwork commented Dec 23, 2018

has there been any progress in the meantime?

Is there a way to use Gooey and PyInstaller on MacOS? How does it work?

@engdan77
Copy link

has there been any progress in the meantime?

Is there a way to use Gooey and PyInstaller on MacOS? How does it work?

Nothing I've heard or seen 🙄 but I would personally be very happy seeing a "success-story" from someone being able to freeze a MacOS application including Gooey and could perhaps help determine if either I was doing something wrong or something had to be fixed in the source to make this work with PyInstaller (or cx_freeze/py2app) somehow. Or confirm my findings.

@john174586
Copy link

@chriskiehl Is there anyupdate on the issue pointed by @engdan77

@john174586
Copy link

After trying different things, I am able to run the MacOS application including Gooey.
@engdan77 @aatwork Just copy an empty folder named "Contents" in the directory that contains MacOS application.
I am still trying to figure out the reason. Is it due to Pyinstaller or Gooey?

@engdan77
Copy link

engdan77 commented Jan 9, 2019

Awesome @john174586 !! I would have never figured that out :-D

I used my previous sample with the difference that I updated the .spec file according to https://chriskiehl.com/article/packaging-gooey-with-pyinstaller to assure languages and images are included and not throwing error because of this. And I ran this "venv/bin/python -m PyInstaller new_test.spec" and within that "dist" folder being created with the binary created I followed your advice creating a "Contents" folder and voila it now starts without any errors.

For the future and others perhaps good to either include this piece of advice within the instructions for PyInstaller for MacOS or perhaps we might figure out if there is anything in Gooey that could be changed to make this work without manually adding this folder before running.

@chriskiehl
Copy link
Owner

A firm, but not too firm -- quality is what I'm talking about -- handshake offered to anyone who adds their OSX how-to to the wiki.

@jrjhealey
Copy link

jrjhealey commented Jul 1, 2019

Hi all,

Somehow, I've managed to get a .app bundle working on MacOS (Mojave 10.14.4 at the time of writing). I'm still not sure exactly what the right minimal combination of components was, and there are some issues still, so I'm not sure its 'wiki-ready'. But perhaps the following will help others. Unfortunately its been quite a long process that I've not been 100% focussed on, so I'm not sure where I got all of the leads that bought me to here, so just consider this a 'dump' of the current state of play!

(A video of the build process here just to show it seems to work https://youtu.be/YxpZQrL8-_g )

This guidance is python3 specific, I should add. In approximately the order I think I hit on things, here goes:

Unbuffered output

This is still an issue, as I've not discovered how to make this work in python3. What I can say, is that the guidance here, about adding these lines, breaks the .app, under Py3, as alluded to in the SO post linked below, this has something to do with PIP3116 I believe.

nonbuffered_stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
sys.stdout = nonbuffered_stdout

I have an SO post open here, looking for an answer to buffered Python3, but so far nothing doing. In the app, literally everything gets dumped to the in-built terminal too, not just the logging I want, so I'm not sure how to separate out these log streams yet either.

*.spec

I think some of the magic comes from having a correct .spec file for pyinstaller. This is where I'm not sure exactly what the key element was, but here's my current working spec file for this functioning .app project in its entirety (I've edited out the app specific bits like name etc). (Repo: https://github.com/jrjhealey/Oread/blob/master/Oread.spec)

# -*- mode: python -*-

import os
import platform
import gooey
gooey_root = os.path.dirname(gooey.__file__)
gooey_languages = Tree(os.path.join(gooey_root, 'languages'), prefix = 'gooey/languages')
gooey_images = Tree(os.path.join(gooey_root, 'images'), prefix = 'gooey/images')

from PyInstaller.building.api import EXE, PYZ, COLLECT
from PyInstaller.building.build_main import Analysis
from PyInstaller.building.datastruct import Tree
from PyInstaller.building.osx import BUNDLE

block_cipher = None

a = Analysis(['APPNAME.py'],
             pathex=['/path/to/APP.py'],
             hiddenimports=[],
             hookspath=None,
             runtime_hooks=None,
             )
pyz = PYZ(a.pure)

options = [('u', None, 'OPTION'), ('v', None, 'OPTION'), ('w', None, 'OPTION')]


exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          options,
          gooey_languages,
          gooey_images,
          name='APPNAME',
          debug=False,
          strip=None,
          upx=True,
          console=False,
          icon=os.path.join(gooey_root, 'images', 'program_icon.ico'))

if platform.system() == 'Darwin':
    info_plist = {'addition_prop': 'additional_value'}
    app = BUNDLE(exe,
                 name='APPNAME.app',
                 bundle_identifier=None,
                 info_plist=info_plist
                )

Building

There are a selection of Mac specific things to be done with pyinstaller to get a functioning standalone .app. These can be found on the manual page, but in short, you can run:

cd package_root/
python -m PyInstaller -F --windowed ./package.spec

--windowed is key for a graphical app bundle. I think -F is optional. Without it, you'll have a distributable folder of bits and pieces, not a singular app bundle though.


Remaining issues

There are still problems with the logging as I mentioned, which I've not yet been able to resolve. Any help from seasoned Python3 logging users would be appreciated.

An .app bundle built with the -F flag to pyinstaller essentially has a frozen python instance bundled with it. It is very slow to open, and I'm not sure what can be done to improve things. It seems to get marginally better on subsequent opens, but I believe this has something to do with the python envionment being uncompressed etc ready for use. This may be unavoidable?

Lastly, not an issue per se but creating a singular .app bundle with -F will lead to the .app being quite large. A basic package such as the repo I linked, ends up yielding a 250Mb+ .app.

The comments above about adding a Contents directory did not seem to make a difference to me. Perhaps thats another Python2 curiosity.


Finally I'll add that I built all of this using python3.6.7, pyinstaller3.4 all installed via conda, with PyCharm:


PyCharm 2018.3.4 (Community Edition)
Build #PC-183.5429.31, built on January 29, 2019
JRE: 1.8.0_152-release-1343-b26 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
macOS 10.14.4

I'll try and update this post with anything else I find out.

@engdan77
Copy link

Thanks for sharing @jrjhealey, just as a fyi I was trying to use your .spec file using PyInstaller 3.5, Python 3.6.6 (using venv) on a MacOS 10.14.5 both using the sample Gooey example as a single file and adding it as a package (using main.py etc) like you did with yours. For some reasons I still have the same behaviour as I've seen before that in the dist/ folder I get an xxxx.app (folder-structure) and a xxxx (just a binary file) and the only way I manage to start the application was by creating an empty folder named "Contents" within dist/ and by running the xxxx (this xxxx.app won't open for some reason). When I get a moment I will try your project using "conda" distribution.

@dnides
Copy link

dnides commented Aug 14, 2019

@engdan77 any fixes for this? Same issue here. Thanks!

@engdan77
Copy link

@engdan77 any fixes for this? Same issue here. Thanks!

Hey @dnides .. the only workable method I found is after you've created a "dist" using PyInstaller you'd need to create an empty folder named "Contents" where you're binary created is found, then it works for me. It does mean though you'd need to do this manually before you distribute this to someone else..

@SagaciousZed
Copy link

Following in the work from @jrjhealey

I've managed to create a working app bundle along with the curiosity of his logging problem
using
Venv Python 3.7.7 , PyInstaller 3.6 , Gooey 1.0.4 (unreleased as of this writing) and macOS 10.13.6

All I've managed to identify is that this seems to be something PyInstaller is dumping to standard out. as it doesn't actually effect logging level of the loggers i can enumerate at runtime. But I have yet been unable to identify what in PyInstaller or Gooey is responsible for this behavior.

@SagaciousZed
Copy link

I have identify the debug information being printed out. It is the verbose output from Python. THe culprit is that we have set the verbose flag in the options passed in the spec

options = [('u', None, 'OPTION'), ('v', None, 'OPTION'), ('w', None, 'OPTION')]

We are probably better off only setting

options= [('u', None, 'OPTION')]

Once I did that in my build all the verbose output went away.

@action456789
Copy link

  1. Create a new folder named A, and create a new folder named content in the folder,
  2. Put the files generated by pyinstaller into folder A
  3. Change the suffix of A to .app, double-click to run
    This worked for me

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants