You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Vispy wrongly detects Spyder as Jupyter notebook #1708
Does %gui qt work in spyder with vispy? I wouldn't expect it to unless it is changing that kernel trait. I don't think there is anything in vispy that is checking the ipython configuration for what graphics backend it was told to use. The %gui qt magic command, if I remember correctly, is hooking a Qt event loop in to IPython in a background thread so you can run Qt applications while still having access to the REPL.
Edit: ...work in spyder with vispy to set the default vispy backend?
This is a limitation of the Jupyter architecture: there's no way to tell what frontend (notebook or Spyder) is requesting an evaluation in the kernel. Besides, since several frontends can be connected to same kernel (e.g. Spyder can easily create a console for a kernel started by the notebook), things are even harder because each request should be handled separately.
However, you could check for the presence of several environment variables that are only present in our kernels (this is the list of env vars we send to the kernel) to give better support for Spyder.
That will fail for a Spyder console connected to a notebook kernel and also for our third-party notebook plugin, but it'll work for every console started normally in Spyder.
Yes. Spyder uses the qtconsole package, which provides an interface very similar to IPython's terminal version but developed in Qt, which can evaluate any command IPython (or more specifically ipykernel) can run.
@impact27, do you think we could improve the detection of a kernel being called by Spyder using the new Comms architecture you developed?
@mwcraig, I don't know if you're using a similar procedure to what I described above in VPython or you came up with a better solution to distinguish between notebook and Spyder there.
I was more wondering if doing it caused vispy to say "ah we should use Qt instead of webgl" even though vispy was not called in any way. I don't think vispy checks anything that %gui qt is affecting.
If the kernel is not a SpyderKernel, the comms will not be connected, and you can't communicate. So you need to know that you are using spyder to use the comm.
@impact27 The issue, if you can consider it one, is that vispy defaults to a specific webgl backend if it detects it is being used in a notebook. The way it does this was based on stackoverflow answers which said get_ipython().kernel should only exist for a notebook. However, that assumed the only alternative was an ipython terminal (where kernel isn't defined) or that get_ipython doesn't exist in which case it is being run by the normal python interpreter.
So when importing vispy in a spyder environment, vispy will default to this webgl backend because it sees that a jupyter kernel is being used. As far as the current checks go it only checks for the existence of a kernel, not what type of kernel it is.
I think the best long term solution is to do an isinstance check right after the kernel check. It will be IPythonKernel in a notebook, otherwise don't assume it is a notebook. @hmaarrfk Do you have time to make a PR for this?
Short term workaround is to explicitly say what backend you want to use as @hmaarrfk pointed out above.
It seems the correct way is to understand what %gui qt and check for the existence of that state. That magic seems applicable even in the case of somebody using a notebook to launch local QT applications. (I believe that is what @jni is doing with napari). Second, it would be to understand if there is any difference between using the %gui qt magic and setting the graphics backend in spyder.
The comms could work if spyder registers a target to open comms and sends back informations when a comm is opened. This is the opposite way as to what is happening in spyder and you wouldn't be sure that a frontend is already connected when you send the message.
Second, it would be to understand if there is any difference between using the %gui qt magic and setting the graphics backend in spyder.
We %matplotlib <backend> to set backends in Spyder instead of %gui <backend>. That's because we want to give users an out of the box experience for Matplotlib.
hmm it seems that both %gui qt and %matplotlib qt create a variable app. This app seems to depend on what graphics backend you choose to have. Maybe that is the variable we should be checking for? Note that if you simply run the %gui magic, it seems to close the app. I'm not a QT expert, so I'm not too sure what variable to check to know if hte app is still running or not
Details
Python 3.7.3 | packaged by conda-forge | (default, Jul 1 2019, 21:52:21)
Type "copyright", "credits" or "license" for more information.
IPython 7.8.0 -- An enhanced Interactive Python.
%gui tk
get_ipython().kernel.app
Out[2]: <tkinter.Tk object .>
%gui qt
ERROR:root:Cannot activate multiple GUI eventloops
%gui
get_ipython().kernel.app
Out[5]: <tkinter.Tk object .>
%gui qt
get_ipython().kernel.app
Out[7]: <PyQt5.QtWidgets.QApplication at 0x7f8891e90ee8>
app = get_ipython().kernel.app
app.destroyed
Out[9]: <bound PYQT_SIGNAL destroyed of QApplication object at 0x7f8891e90ee8>
%gui
%gui tk
app = get_ipython().kernel.app
app
Out[13]: <tkinter.Tk object .>
That's an interesting idea. However, on my ipython terminal with same version of python and ipython from conda-forge (on Ubuntu) my get_ipython() doesn't have a kernel. Or is your above output from a spyder session?
Ok I think I like this. Just tested the %gui qt stuff in a notebook just to make sure and the behavior is similar. Even if you do %gui notebook or %gui ipympl it doesn't create the app attribute because I'm guessing it isn't needed (we're already using the javascript/browser event loop). So if we check that a kernel attribute exists that means we are running on some "remote" kernel. If that kernel has an app attribute then that means the user or some other system (spyder) has explicitly set what GUI backend to use (for matplotlib or other GUI tools) and vispy can safely assume it shouldn't use the webgl widget/backend.
If this app has a different behavior/existence when multiple frontends are connected to the same kernel then we can deal with that at a later time. At that point people should be explicitly setting their backends anyway.
Activity
hmaarrfk commentedon Sep 12, 2019
The workaround is to have
but that only happens if you remember to use this before starting any kind of application.
hmaarrfk commentedon Sep 12, 2019
Potentially use
get_ipython().kernel.app???On Spyder
Jupyter Notebook
jni commentedon Sep 13, 2019
We use vispy at napari but we use %gui=qt in notebooks, and I presume also in Spyder. (I have the equivalent command in my ipython config.)
djhoese commentedon Sep 13, 2019
@hmaarrfk In your original post, was that ipython output or spyder?
On my linux system in ipython:
On same linux system with jupyter notebook and jupyter lab:
Is there a jupyter dev that we can ask for the most reliable way of doing this? Maybe the ipywidgets folks know, I'll ping their gitter.
Edit: https://stackoverflow.com/a/39662359
hmaarrfk commentedon Sep 13, 2019
That's all from Spyder. Spyder, like the jupyter software, builds ontop of the ipython kernel.
hmaarrfk commentedon Sep 13, 2019
I saw those posts, their suggestions end up converging to what you did, but that doesn't seem to detect the difference too well.
hmaarrfk commentedon Sep 13, 2019
Maybe
%gui qtis the only reliable way to specify the backend.That said, I thought that is what selecting the graphics backend from the settings in Spyder did. Maybe that is a bad assumption
djhoese commentedon Sep 13, 2019
Does
%gui qtwork in spyder with vispy? I wouldn't expect it to unless it is changing that kernel trait. I don't think there is anything in vispy that is checking the ipython configuration for what graphics backend it was told to use. The%gui qtmagic command, if I remember correctly, is hooking a Qt event loop in to IPython in a background thread so you can run Qt applications while still having access to the REPL.Edit: ...work in spyder with vispy to set the default vispy backend?
ccordoba12 commentedon Sep 13, 2019
This is a limitation of the Jupyter architecture: there's no way to tell what frontend (notebook or Spyder) is requesting an evaluation in the kernel. Besides, since several frontends can be connected to same kernel (e.g. Spyder can easily create a console for a kernel started by the notebook), things are even harder because each request should be handled separately.
However, you could check for the presence of several environment variables that are only present in our kernels (this is the list of env vars we send to the kernel) to give better support for Spyder.
That will fail for a Spyder console connected to a notebook kernel and also for our third-party notebook plugin, but it'll work for every console started normally in Spyder.
ccordoba12 commentedon Sep 13, 2019
Yes. Spyder uses the qtconsole package, which provides an interface very similar to IPython's terminal version but developed in Qt, which can evaluate any command IPython (or more specifically
ipykernel) can run.ccordoba12 commentedon Sep 13, 2019
Pinging @impact27 and @mwcraig about this:
djhoese commentedon Sep 13, 2019
I was more wondering if doing it caused vispy to say "ah we should use Qt instead of webgl" even though vispy was not called in any way. I don't think vispy checks anything that
%gui qtis affecting.mwcraig commentedon Sep 13, 2019
Yep, we are just checking for an environment variable with the string "SPYDER" in it in vpython.
impact27 commentedon Sep 13, 2019
I am not sure I understand what the problem is. can't you just call
get_ipython().kernel.__class__?impact27 commentedon Sep 13, 2019
With Jupyter notebook:
With spyder:
impact27 commentedon Sep 13, 2019
If the kernel is not a
SpyderKernel, the comms will not be connected, and you can't communicate. So you need to know that you are using spyder to use the comm.djhoese commentedon Sep 13, 2019
@impact27 The issue, if you can consider it one, is that vispy defaults to a specific webgl backend if it detects it is being used in a notebook. The way it does this was based on stackoverflow answers which said
get_ipython().kernelshould only exist for a notebook. However, that assumed the only alternative was an ipython terminal (where kernel isn't defined) or thatget_ipythondoesn't exist in which case it is being run by the normal python interpreter.So when importing vispy in a spyder environment, vispy will default to this webgl backend because it sees that a jupyter kernel is being used. As far as the current checks go it only checks for the existence of a kernel, not what type of kernel it is.
I think the best long term solution is to do an isinstance check right after the
kernelcheck. It will beIPythonKernelin a notebook, otherwise don't assume it is a notebook. @hmaarrfk Do you have time to make a PR for this?Short term workaround is to explicitly say what backend you want to use as @hmaarrfk pointed out above.
ccordoba12 commentedon Sep 13, 2019
The thing is Spyder can connect to an IPythonKernel without problems. I mean, you can start a kernel in a terminal with
then pass its connection file to our "Connect to an existing kernel" dialog and keep working with it just fine.
But your solution will work for all kernels started by Spyder directly (which I guess are most kernels started by our users anyway).
hmaarrfk commentedon Sep 13, 2019
It seems the correct way is to understand what
%gui qtand check for the existence of that state. That magic seems applicable even in the case of somebody using a notebook to launch local QT applications. (I believe that is what @jni is doing with napari). Second, it would be to understand if there is any difference between using the%gui qtmagic and setting the graphics backend in spyder.impact27 commentedon Sep 13, 2019
The comms could work if spyder registers a target to open comms and sends back informations when a comm is opened. This is the opposite way as to what is happening in spyder and you wouldn't be sure that a frontend is already connected when you send the message.
ccordoba12 commentedon Sep 14, 2019
We
%matplotlib <backend>to set backends in Spyder instead of%gui <backend>. That's because we want to give users an out of the box experience for Matplotlib.hmaarrfk commentedon Sep 14, 2019
hmm it seems that both
%gui qtand%matplotlib qtcreate a variableapp. Thisappseems to depend on what graphics backend you choose to have. Maybe that is the variable we should be checking for? Note that if you simply run the%guimagic, it seems to close the app. I'm not a QT expert, so I'm not too sure what variable to check to know if hte app is still running or notDetails
djhoese commentedon Sep 14, 2019
That's an interesting idea. However, on my ipython terminal with same version of python and ipython from conda-forge (on Ubuntu) my
get_ipython()doesn't have a kernel. Or is your above output from a spyder session?hmaarrfk commentedon Sep 14, 2019
yeah, sorry, it is from a spyder session.
djhoese commentedon Sep 14, 2019
Ok I think I like this. Just tested the
%gui qtstuff in a notebook just to make sure and the behavior is similar. Even if you do%gui notebookor%gui ipymplit doesn't create theappattribute because I'm guessing it isn't needed (we're already using the javascript/browser event loop). So if we check that a kernel attribute exists that means we are running on some "remote" kernel. If thatkernelhas anappattribute then that means the user or some other system (spyder) has explicitly set what GUI backend to use (for matplotlib or other GUI tools) and vispy can safely assume it shouldn't use the webgl widget/backend.If this
apphas a different behavior/existence when multiple frontends are connected to the same kernel then we can deal with that at a later time. At that point people should be explicitly setting their backends anyway.hmaarrfk commentedon Sep 14, 2019
Maybe we need to add a secondary check:
First check for the kernel, then check if the kernel has an active graphical backend, through the app attribute
hmaarrfk commentedon Sep 15, 2019
I guess the problem with checking
get_ipython().kernel.appis thatkerneldoesnt' exist for ipython consoles.That said, they can still use the
%gui qtline magic, and likely should to get hooked into the event loop.One could check
get_ipython().active_eventloop, which seems to have the following values:%gui qt%gui qtI mostly put the name of the interested parties next to them so that they may chime in the testing phase should it be necessary.