Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

pythonw should not redefine PYTHONEXECUTABLE #446

Open
astrofrog opened this issue Sep 16, 2015 · 28 comments
Open

pythonw should not redefine PYTHONEXECUTABLE #446

astrofrog opened this issue Sep 16, 2015 · 28 comments

Comments

@astrofrog
Copy link

This is related to (but not exactly the same as) #199, and is also request 907 in the continuum support system.

In Anaconda, unlike other distributions these days, python is different from pythonw, and the latter is needed to run scripts that use e.g. PyQt4 to get everything to work correctly (see also #199)

For some packages, such as the developer version of the glue package, and any other GUI packages, I therefore need to install the package with:

pythonw setup.py install

This should in principle ensure that the interpreter used for installed scripts is pythonw. However, in conda, the pythonw script does the following:

export PYTHONEXECUTABLE=/Users/tom/miniconda3/envs/production/bin/python

before running python.app.

This is a problem, because it means that running

pythonw setup.py install

basically has no effect compared to installing with python, and the installed scripts will just be run with python instead of pythonw or python.app (this behavior is unlike other distributions). If I comment out this line, everything works as expected.

Would it be possible to remove the line setting PYTHONEXECUTABLE from pythonw? At the moment, I cannot install GUI packages properly with pythonw setup.py install, and making a conda package each time before installing is not realistic, since I am doing a lot of development on these packages, so need to install them often.

Of course, the ideal solution is that python should just be the same as pythonw as discussed in #199, but at the very least in the mean time, I think that the export PYTHONEXECUTABLE line should be removed since it causes issues when installing scripts.

I am using the OSX version of anaconda by the way.

(also cc-ing @ChrisBarker-NOAA and @asmeurer since you were discussing this in #199)

@ccordoba12
Copy link

@ilanschnell?

@ChrisBarker-NOAA
Copy link

On Wed, Sep 16, 2015 at 8:09 AM, Thomas Robitaille <notifications@github.com

wrote:

For some packages, such as the developer version of the glue package, and
any other GUI packages, I therefore need to install the package with:

pythonw setup.py install

This should in principle ensure that the interpreter used for installed
scripts is pythonw.

hmm -- does that ever work ?

in conda, the pythonw script does the following:

export PYTHONEXECUTABLE=/Users/tom/miniconda3/envs/production/bin/python

before running python.app.

This is a problem, because it means that running

pythonw setup.py install

basically has no effect compared to installing with python, and the
installed scripts will just be run with python instead of pythonw or
python.app (this behavior is unlike other distributions). If I

comment out this line, everything works as expected.

interesting.

Would it be possible to remove the line setting PYTHONEXECUTABLE from
pythonw?

Anyone know what PYTHONEXECUTABLE is used for? The trick is the pythonw
isn't really an executable, as you well know.

but maybe it should be set to the executable in the app bundle, as that's
the one actually being used to run the code...

At the moment, I cannot install GUI packages properly with pythonw
setup.py install, and making a conda package each time before installing
is not realistic, since I am doing a lot of development on these packages,
so need to install them often.

Of course, the ideal solution is that python should just be the same as
pythonw as discussed in #199
#199,

indeed -- it would be nice to have that all "just work" that way it has in
the python.org distribution for years.

Does anyone know if there is a technical reason it's not done the way it is
in the python.org distro? OR is is just that someone would have to write
the code?

-Chris

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

@ilanschnell
Copy link
Contributor

PYTHONEXECUTABLE is set to fix argv[0] in Modules/main.c

@ilanschnell
Copy link
Contributor

Why do you want to use pythonw setup.py install to install GUI applications? I would say that python setup.py install should also work, and do the same thing.

@ChrisBarker-NOAA
Copy link

"""PYTHONEXECUTABLE is set to fix argv[0] in Modules/main.c"""

Is there a reason that that shouldn't be the one inside the app bundle?

@ChrisBarker-NOAA
Copy link

python setup.py install doesn't that start up the app with what PYTHONEXECUTABLE is set to?

OR si what the needs is a pythonw in the #! line?

In any case, still nicer to get rid of the need for pythonw -- easier cross platform coding.

@astrofrog
Copy link
Author

@ilanschnell @ChrisBarker-NOAA

Here is a nice example for why pythonw is needed. On MacOS X 10.9 or 10.10 (specifically those versions, not 10.8), run the following script with python:

from PyQt4.QtGui import QApplication, QMainWindow, QMenu

app = QApplication([''])
main = QMainWindow()
mbar = main.menuBar()
menu = QMenu(mbar)
menu.setTitle("&File")
mbar.addMenu(menu)
main.show()
main.raise_()
app.exec_()

What you will see is that the menu doesn't appear straight away (you have to switch application then back to get it to work). Now try running the program again with pythonw - it works!

Basically pythonw is needed to iron out these kinds of GUI issues. In conda I could also run the script with the python.app command.

Now let's take a more complicated example - let's say I want to install the glueviz package from the git repository (to get the latest version, as opposed to using the conda package):

git clone git@github.com:glue-viz/glue.git
cd glue
python setup.py install

Now if I try and start glue on MacOS X 10.9 and 10.10 by running the glue command, the menubar doesn't appear. This is because when installing glue, it installs a glue script using an entry point, and the first line of the script is set to:

#!/Users/tom/miniconda3/envs/production/bin/python

So it uses the normal Python, and is the same as running the simple script higher up with python. Now if I run:

pythonw setup.py install

Nothing changes because of the export statement in the pythonw script. If I remove that line, and run pythonw setup.py install again, then now the glue script has the following first line:

#!/bin/bash /Users/tom/miniconda3/envs/production/bin/python.app

and so when I run glue, everything works as normal!

The reason why people usually never install the GUI packages with pythonw is because in most other installations, python is pythonw.

Does this make more sense?

@astrofrog
Copy link
Author

I am cc-ing @ChrisBeaumont in case I missed anything out

@ChrisBeaumont
Copy link

That sounds right to me.

It would be great if pip install gui_package or python setup.py install worked in anaconda (ie pythonw and python are aliases of each other, and behave like what is currently called pythonw). As it stands you need pythonw -m pip install gui_package or pythonw setup.py install, along with the workaround proposed in this issue.

@astrofrog
Copy link
Author

@ilanschnell - I'm now seeing issues due to this in the latest version of MacOS X. If I check out the source code of the glueviz package (https://github.com/glue-viz/glue) and then do:

python setup.py install

then when I start up glueviz with glue, the menu bar is not responsive until I click outside the application and back in it. This is not a problem with the conda package, just if I install from source into Anaconda. If I try:

python.app setup.py install

it still doesn't work, and still creates a glue script that starts with:

#!/Users/tom/miniconda3/envs/dev35/bin/python

For comparison, if I install the conda glueviz package, the first line is:

#!/bin/bash /Users/tom/miniconda3/envs/dev35/bin/python.app

I think this is still the same issue as here - can you suggest a workaround?

@astrofrog
Copy link
Author

@ilanschnell - if I install with:

python.app setup.py install

then change the first line of glue from:

#!/Users/tom/miniconda3/envs/dev35/bin/python

to

#!/bin/bash /Users/tom/miniconda3/envs/dev35/bin/python.app

it then works fine. Is there any way to make it so that when installing with:

python.app setup.py install

the first line of the script is set correctly?

@ChrisBarker-NOAA
Copy link

On Sun, May 22, 2016 at 10:00 AM, Thomas Robitaille <
notifications@github.com> wrote:

@ilanschnell https://github.com/ilanschnell - if I install with:

python.app setup.py install

then change the first line of glue from:

#!/Users/tom/miniconda3/envs/dev35/bin/python

to

#!/bin/bash /Users/tom/miniconda3/envs/dev35/bin/python.app

couldn't that be:

/Users/tom/miniconda3/envs/dev35/bin/pythonw

which is the python convention for windowing apps.

it then works fine. Is there any way to make it so that when installing

with:

python.app setup.py install

the first line of the script is set correctly?

I don't think so, because it's setuptools that is making the script
wrapper, and it is simply broken in this regard.

Alternatively, you could say Anaconda is broken, as the python.org build
has had "python" and "pythonw" the same for many years. I still have no
idea why Anaconda is not built the same way as the python.org build -- this
would all go away if it were.

This was posted as an issue on the setuptools project a while back:

pypa/setuptools#410

I suppose one of us needs to submit an actual patch..

-CHB


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#446 (comment)

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

@ijstokes
Copy link

From @ChrisBarker-NOAA on Dec 12 2016, Anaconda ML:

conda folks:

PING!!! one more good reason to make your default python interpreter GUI compatible -- like the python.org build does -- it would solve all these problems.

As for getting ipython to run under pythonw, I have no idea :-(

unfortunately the setuptools entry-points does not do the right thing -- though I"m not sure that ipython uses that anyway.

That part may be a question for the ipython folks.

-CHB

@BjornFJohansson
Copy link

+1 fo solving this! conda convert does not work for scripts with entry points if they use wxpython for example.

@pllim
Copy link

pllim commented Mar 24, 2017

Also seems to affect Ginga (see ejeschke/ginga#441).

@ChrisBarker-NOAA
Copy link

Since this is getting Pinged again, I"ll try a little summary:

Apple, in its Infinite Wisdom doesn't allow regular old command line apps to access the GUI (or at least not properly). GUI apps MUST be run from inside an "application bundle" -- you can look elsewhere for details, but that's how I understand it. So regular old unix-style-build provided python executable won't work.

History: back in the day, the windows build of python provided a "python" and "pythonw" executable (I don't know if it still does...) and one would bring up a console for you (for stdout and stdin), and one wouldn't. Meanwhile, the Mac build did a similar thing -- so it was kind of a standard that GUI apps would be run with "pythonw" and console apps with "python".

Eventually, the folks creating the Mac builds developed a (kinda kludgy) way to make a small executable that would run inside an app bundle, but also be lightweight enough to be the main command line executable as well -- so for quite some time, the python.org builds shipped a "python" and a "pythonw", but they were aliases for the same thing, and both would behave exactly the same.

However, there was also a bunch of other complications and Mac-specific stuff in the python.org builds: "Framework Builds", "Fat binaries", PPC vs Intel vs 32bit vs 64bit.... So someone hacked together a build system that would build various combinations of these builds. But there is the rub -- there is no easy way to build a regular old unix style (non-framework) build with the pythonw executable.

So when Continuum came along to setup Anaconda, they chose the Unix-style build, as they didn't want all the Framework and Fat build overhead. But this did not get them the nifty pythonw hack.

So, in order to make GUI apps work, continuum provides the "python.app" package, which provides a application bundle with a python executable in it, (and a couple other things to make qt work) and a "pythonw" shell script in bin that re-directs to that app bundle python (but setting PYTHONEXECUTABLE to the regular executable) -- this allows the OS to see an executable in an application bundle, so ti's happy, but the rest of Python sees the regular one, which it needs to, as the rest of the Python install is not in the bundle.

So what's the problem?

I've lost track of all the issues, but I think that the fact that pythonw is a shell script, rather than a proper executable causes some issues. But I know that the main issue is that setuptools doesn't have respect the "pythonw" concept. So if setuptools is used to install a script with "entry points" or whatever, it used plain "python", so the script won't work. Also, since pythonw is a shell script that re-directs, you can't just hack the startup script that setuptools builds, and you can't run "setup.py install" with pythonw either. (and no, I don't fully understand these complications, but I do know the simple and obvious things don't work)

Solutions:

I think there are essentialy two possible routes to a solution:

  1. patch setuptools to use pythonw for windowed applications.
  • However, there are issues on the setuptools project, and no one seems interested in doing that. plus setuptools is a bit of a Frankenstein's monster with an uncertain future (it's not going away, but it may be substantially refactored). And it's not as simple as replacing "python" with "pythonw", due to the redirection script. But if someone wants to work on a patch and submit it -- maybe it will take.
  1. update the Anaconda python build to build the python/pythonw executable. I think the is the easiest and most robust way to solve this problem. It would require some hacking of the build scripts for python, so someone that knows a bit about autotools would have to do it. I planned to sit down with Ned Deily last year at the PyCon Sprints to figure it out, but ended up working on something else :-(.

Continuum hasn't addressed this in ages (I think GUI apps are just not a major driver, and the pythonw solution they have mostly works). My suggestion, if someone can find the energy and time to work on this, is to contribute the fix to the conda-forge python build. Then folks would have access to it, and maybe Continuum would pick it up for the official builds once it proves itself.

https://github.com/conda-forge/python-feedstock

Anyway, it'll never get fixed unless someone puts some time into it!

@mingwandroid
Copy link

mingwandroid commented Mar 24, 2017 via email

@ChrisBarker-NOAA
Copy link

ChrisBarker-NOAA commented Mar 24, 2017 via email

@mingwandroid
Copy link

mingwandroid commented Mar 24, 2017 via email

@ChrisBarker-NOAA
Copy link

ChrisBarker-NOAA commented Mar 24, 2017 via email

@mingwandroid
Copy link

mingwandroid commented Mar 26, 2017

@astrofrog, @ChrisBarker-NOAA, @pllim, @ijstokes, @BjornFJohansson: Continuum's Python executable (I tested with 3.6.1) dynamically links to Cocoa's CoreFoundation library (which means our interpreter is GUI compatible). We do not provide an executable that does not do this, whereas CPython releases have two different executables, one which does link to CoreFoundation (Resources/Python.app/Contents/MacOS/Python) and one which does not (bin/python3.6).

This dynamic linkage can be seen from otool -l /Library/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents/MacOS/Python:

Load command 11
          cmd LC_LOAD_DYLIB
      cmdsize 104
         name /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 550.29.0
compatibility version 150.0.0
Load command 12

With respect to entry points, I want conda/conda-build to do 'the right thing', but I cannot find anywhere that details what exactly that is. Can someone point me to some documentation for that? All I've found so far is:
https://setuptools.readthedocs.io/en/latest/setuptools.html#dynamic-discovery-of-services-and-plugins

I installed the official CPython 3.6.1 and wrote a simple test containing this setup.py:

setup(name='hello_world_setuptools',
      version='0.1.0',
      packages=['hello_world_setuptools'],
      entry_points={
          'console_scripts': [
              'hello_world_setuptools = hello_world_setuptools.__main__:main'
          ],
          'gui_scripts': [
              'hello_world_setuptools_gui = hello_world_setuptools.__main__:main'
          ]
      },
     )

I would have hoped that installing this via $PYTHON setup.py install, Python would have created entry points scripts using each of these two Python executables, but that does not seem to be the case. For both, the entry-point used is the python interpreter used to run setup.py (to do what I think I wanted, the interpreters would have to know about each other or setuptools would have to hardcode some logic to handle this).

@ChrisBarker-NOAA
Copy link

ChrisBarker-NOAA commented Mar 27, 2017

This is all confusing, but I'm pretty sure you have the issues somewhat confused:

Continuum's Python executable (I tested with 3.6.1) dynamically links to Cocoa's CoreFoundation library (which means our interpreter is GUI compatible). We do not provide an executable that does not do this,

it does indeed link to CoreFoundation:

$ otool -L python
python:
	/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 635.21.0)
	@rpath/libpython3.5m.dylib (compatibility version 3.5.0, current version 3.5.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)

but I don't think that is "Cocoa", but rather other core OS-X stuff:

https://developer.apple.com/reference/corefoundation

and, indeed, when I try to run, for instance wxPython, with that very executable, I get:

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.

but it does run with pythonw.

And with the python embedded in the python.app:

~/miniconda3/python.app/Contents/MacOS/python MicroApp.py

So -- with the python provided by conda -- you need to run your app with the python inside python.app -- either directly or from pythonw.

With respect to entry points, I want conda/conda-build to do 'the right thing',

This isn't conda build thing -- it's a setuptools thing -- all conda build does is make a package out of whatever your build script installs. Which means we need to:

  1. change the conda python/pythonw to do the trick that the python.org build does.
    or
  2. patch setuptools to "respect" pythonw for GUI app entry points
    or
  3. add a hack in your conda build script that monkey patches the entry point scripts.

I think option (1) is the "right" way to solve the problem, but options (3) is the only one you can do right now.

For both, the entry-point used is the python interpreter used to run setup.py (to do what I think I wanted, the interpreters would have to know about each other or setuptools would have to hardcode some logic to handle this).

exactly -- setuptools SHOULD use pythonw for gui_scripts -- why do they even HAVE gui_scripts if it's not going to do anything different.

But maybe you can hack around it.

I tried the really simple approach of hand editing the script that setuptools creates, and replacing "python" with "pythonw" -- that failed, I think because pythonw is a bash script, not a proper executable.

But maybe you could try patching in the full path to the python inside the app bundle.

or maybe make essentially a copy of the pythonw script.

If one of those works, then you at least know what you are trying to hack in....

Once you have it working, we could maybe propose a patch to setuptools (though it it' specific to the conda setup, that's not going to fly). Or maybe conda-build could do some hacking -- there are a number of python-specific features in conda -- why not this one?

Another issue -- the conda pythonw script hard-codes the installed path -- you may need to do that, too. I think conda install patches some paths on install, but you'll need to figure out how to trigger that feature...

-CHB

-CHB

@mingwandroid
Copy link

Thanks Chris, Cocoa is not only the GUI part of macOS, it is the entire system that came from NextStep and replaced Carbon.

https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/Cocoa.html

I'll look into this stuff more when I have a chance.

@ChrisBarker-NOAA
Copy link

I can never keep track of Apple's Branding...

But anyway, we know that simply linking against CoreFramework does not get you the ability to run GUI apps with a Python executable.

The folks that understand this stuff can be found on the python-mac list:

https://mail.python.org/mailman/listinfo/pythonmac-sig

a question there might get you the info yu need.

Here is the old discussion:

https://mail.python.org/pipermail/pythonmac-sig/2014-August/024079.html

Note that reading that again, it seems there may be another trick that could be used -- wx, qt, etc could do what TK does -- not that I have any idea what that is. Though I think I prefer a solution that doesn't require all the GUI frameworks to adapt...

-CHB

@BjornFJohansson
Copy link

Hi all, What is the status of this in 2019? I recently packaged a wxpython script as a conda
package which works nicely on Linux and Windows but gives

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.

I am under the impression that this was not solved.
Is there a way to hack around this in setup.py and/or meta.yaml to make this work?

Thanks!

@ChrisBarker-NOAA
Copy link

I'm pretty sure that the answer to the key question is "no" -- in short. nothing has changed.

However, you can add a dependency in your meta.yaml on "python.app" (for only osx)"

requirements:
    ...
    python.app  #[osx]
    ...

then you need to make sure that the app gets run with "pythonw", rather than python -- which is pretty easy on a #! line or command line, but I couldn't find a way to use setuptools entry points to respect that :-(

I really wish that conda built "pythonw" the same way that the python.org builds do, but I've never had the time to figure out how to do that -- I'm no autoconf expert.

@BjornFJohansson
Copy link

Thanks I will try that. Meanwhile, I found this question at SO. He uses pythonw pip install ... on Windows in order not to have a window pop up during the process. If we substitute python setup.py install in the meta.yaml with python pip install on Mac? I did not test this as I don't have a Mac available.

@ChrisBarker-NOAA
Copy link

ChrisBarker-NOAA commented Jun 18, 2019 via email

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

No branches or pull requests

9 participants