Repository: spyder-ide/spyder

Issue:
Spyder 5.2.1 stuck connecting to kernel when using the Tk backend on Windows
## Description

### What steps will reproduce the problem?

<!--- You can use Markdown here --->


Using Win10.
Downloaded Spyder 5.2.1 from spyder-ide.org

1) Create a virtualenv with Python 3.10
2) pip install spyder-kernels==2.2.*
3) Change default environment to the new one
4) Launch Spyder and IPython console runs nicely
5) pip install matplolib in the environment
6) launch new console
7) Connecting to kernel ... (forever)




## Versions

* Spyder version: 5.2.1 
* Python version: 3.7.9
* Qt version: 5.12.10
* PyQt5 version: 5.12.3
* Operating System: Windows 10

### Dependencies

```
# Mandatory:
atomicwrites >=1.2.0          :  1.4.0 (OK)
chardet >=2.0.0               :  4.0.0 (OK)
cloudpickle >=0.5.0           :  2.0.0 (OK)
cookiecutter >=1.6.0          :  1.7.3 (OK)
diff_match_patch >=20181111   :  20200713 (OK)
intervaltree                  :  None (OK)
IPython >=7.6.0               :  7.30.1 (OK)
jedi >=0.17.2;<0.19.0         :  0.18.1 (OK)
jellyfish >=0.7               :  0.8.9 (OK)
jsonschema >=3.2.0            :  4.2.1 (OK)
keyring >=17.0.0              :  23.4.0 (OK)
nbconvert >=4.0               :  6.3.0 (OK)
numpydoc >=0.6.0              :  1.1.0 (OK)
paramiko >=2.4.0              :  2.8.1 (OK)
parso >=0.7.0;<0.9.0          :  0.8.3 (OK)
pexpect >=4.4.0               :  4.8.0 (OK)
pickleshare >=0.4             :  0.7.5 (OK)
psutil >=5.3                  :  5.8.0 (OK)
pygments >=2.0                :  2.10.0 (OK)
pylint >=2.5.0                :  2.12.2 (OK)
pyls_spyder >=0.4.0           :  0.4.0 (OK)
pylsp >=1.3.2;<1.4.0          :  1.3.3 (OK)
pylsp_black >=1.0.0           :  1.0.1 (OK)
qdarkstyle =3.0.2             :  3.0.2 (OK)
qstylizer >=0.1.10            :  0.2.1 (OK)
qtawesome >=1.0.2             :  1.1.1 (OK)
qtconsole >=5.2.1;<5.3.0      :  5.2.2 (OK)
qtpy >=1.5.0                  :  1.11.3 (OK)
rtree >=0.9.7                 :  0.9.7 (OK)
setuptools >=49.6.0           :  59.6.0 (OK)
sphinx >=0.6.6                :  4.3.1 (OK)
spyder_kernels >=2.2.0;<2.3.0 :  2.2.0 (OK)
textdistance >=4.2.0          :  4.2.2 (OK)
three_merge >=0.1.1           :  0.1.1 (OK)
watchdog                      :  2.1.6 (OK)
zmq >=17                      :  22.3.0 (OK)

# Optional:
cython >=0.21                 :  0.29.25 (OK)
matplotlib >=2.0.0            :  3.5.1 (OK)
numpy >=1.7                   :  1.19.3 (OK)
pandas >=1.1.1                :  1.3.5 (OK)
scipy >=0.17.0                :  1.7.3 (OK)
sympy >=0.7.3                 :  1.9 (OK)
```



Discussion:
The IPython console launches if I unninstall matplotlib.
Hey @trierweiler, thanks for opening this issue! Are you also seeing the error you reported in https://github.com/spyder-ide/spyder/issues/16765#issuecomment-991313431?
Please also describe the steps you followed to

> Create a virtualenv with Python 3.10
I observed something similar (see https://github.com/spyder-ide/spyder-kernels/issues/347). Having the backend set to "Automatic" and not having pyqt5 installed, or choosing "Tkinter" as backend causes the console to be stuck on "Connecting to kernel...". @trierweiler Have you tried changing backend under Tools>Preferences>IPython console>Graphics and starting a new console, in case the behavior is similar?
Thank you, it solved the problem. I installed pyqt5 and chose "Automatic"
instead of "Tkinter" as backend.

On Wed, Dec 15, 2021 at 9:42 AM Reinert Huseby Karlsen <
***@***.***> wrote:

> I observed something similar (see spyder-ide/spyder-kernels#347
> <https://github.com/spyder-ide/spyder-kernels/issues/347>). Having the
> backend set to "Automatic" and not having pyqt5 installed, or choosing
> "Tkinter" as backend causes the console to be stuck on "Connecting to
> kernel...". @trierweiler <https://github.com/trierweiler> Have you tried
> changing backend under Tools>Preferences>IPython console>Graphics and
> starting a new console, in case the behavior is similar?
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/spyder-ide/spyder/issues/17024#issuecomment-994755518>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/ADMDJIFKUQRPVLUUE4IWTSTURCELXANCNFSM5KCIYOWA>
> .
> Triage notifications on the go with GitHub Mobile for iOS
> <https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
> or Android
> <https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
>
>


-- 
Gabriel Trierweiler Ribeiro

Running "%matplotlib tk" in an ipykernel console results in:
```
C:\ProgramData\Anaconda3\lib\site-packages\ipykernel\eventloops.py:259: RuntimeWarning: coroutine 'Kernel.do_one_iteration' was never awaited
  self.func()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
```
So it is likely that the tk eventloop is broken in ipykernel since  [#632](https://github.com/ipython/ipykernel/pull/632)
See: https://github.com/ipython/ipykernel/issues/742
Thanks @impact27 for your help with this!

It seems the fix is relatively simple (just running synchronously the `do_one_iteration` coroutine). I'll try to take a look at it later today.
Well you can't because then the loops would be nested. Unless you use https://github.com/erdewit/nest_asyncio. But that might be a hard sell for ipykernel. I think the entrire tk eventloop has to be rewritten. THe solutions I see are to:
 - Force ipykernel<6
 - Disable tk backend
`nest_asyncio` is already a dependency of `jupyter_client`, so we can proceed with that solution:

https://github.com/jupyter/jupyter_client/blob/0eb492726cc279fdb3e2ff690cb62e8a69182d0d/jupyter_client/utils.py#L11-L29

I was thinking to use that `run_sync` function to fix the problem, but since you seem better acquainted with it, could you give me a hand to solve it?
I opened https://github.com/ipython/ipykernel/pull/830
Thanks a lot @impact27!

Resolving patch:
diff --git a/external-deps/spyder-kernels/setup.py b/external-deps/spyder-kernels/setup.py
--- a/external-deps/spyder-kernels/setup.py
+++ b/external-deps/spyder-kernels/setup.py
@@ -40,12 +40,13 @@ def get_version(module='spyder_kernels'):
     'backports.functools-lru-cache; python_version<"3"',
     'cloudpickle',
     'ipykernel<5; python_version<"3"',
-    'ipykernel>=5.3.0; python_version>="3"',
+    'ipykernel>=6.6.1; python_version>="3"',
     'ipython<6; python_version<"3"',
     'ipython>=7.6.0,<8; python_version>="3"',
     'jupyter-client>=5.3.4,<6; python_version<"3"',
     'jupyter-client>=7.1.0; python_version>="3"',
-    'pyzmq>=17',
+    'pyzmq>=17,<20; python_version<"3"',
+    'pyzmq>=22.1.0; python_version>="3"',
     'wurlitzer>=1.0.3;platform_system!="Windows"',
 ]
 


Test patch:
diff --git a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
--- a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
+++ b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
@@ -330,7 +330,6 @@ def test_auto_backend(ipyconsole, qtbot):
 
 @flaky(max_runs=3)
 @pytest.mark.tk_backend
-@pytest.mark.skipif(os.name == 'nt', reason="Fails on Windows")
 def test_tk_backend(ipyconsole, qtbot):
     """Test that the Tkinter backend was set correctly."""
     # Wait until the window is fully up