Repository: spyder-ide/spyder

Issue:
Spyder-kernels message not shown on Windows after restarting kernels
## Problem Description
I installed  Spyder 5.4.0 with Windows installer
I used conda install a python env, didn't install other python package
```
conda create -n paddle3.8.13 python=3.8.13
```
Then  changed to the interpreter of paddle3.8.13, restart kernel

![image](https://user-images.githubusercontent.com/1759365/201035861-fac4219b-5683-48c0-827c-da8c57426c07.png)

Next, change to the interpreter in a previous Python environment, which has installed spyder using conda, restart kernel,it is ok

### What steps reproduce the problem?

https://user-images.githubusercontent.com/1759365/201037425-2fd073ef-6725-4b02-8916-23e34c2603f2.mp4



## Versions
* Spyder version: 5.4.0  (standalone)
* Python version: 3.8.10 64-bit
* Qt version: 5.15.2
* PyQt5 version: 5.15.7
* Operating System: Windows 10
### Dependencies
<!--- Please go to the menu entry Help > Dependencies,
press the Copy to clipboard button and paste below --->

```
# Mandatory:
atomicwrites >=1.2.0                 :  1.4.1 (OK)
chardet >=2.0.0                      :  5.0.0 (OK)
cloudpickle >=0.5.0                  :  2.2.0 (OK)
cookiecutter >=1.6.0                 :  2.1.1 (OK)
diff_match_patch >=20181111          :  20200713 (OK)
intervaltree                         :  None (OK)
IPython >=7.31.1;<8.0.0              :  7.34.0 (OK)
jedi >=0.17.2;<0.19.0                :  0.18.1 (OK)
jellyfish >=0.7                      :  0.9.0 (OK)
jsonschema >=3.2.0                   :  4.17.0 (OK)
keyring >=17.0.0                     :  23.9.3 (OK)
nbconvert >=4.0                      :  7.2.3 (OK)
numpydoc >=0.6.0                     :  1.5.0 (OK)
paramiko >=2.4.0                     :  2.11.0 (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.9.3 (OK)
pygments >=2.0                       :  2.13.0 (OK)
pylint >=2.5.0;<3.0                  :  2.15.5 (OK)
pylint_venv >=2.1.1                  :  2.3.0 (OK)
pyls_spyder >=0.4.0                  :  0.4.0 (OK)
pylsp >=1.6.0;<1.7.0                 :  1.6.0 (OK)
pylsp_black >=1.2.0                  :  1.2.1 (OK)
qdarkstyle >=3.0.2;<3.1.0            :  3.0.3 (OK)
qstylizer >=0.2.2                    :  0.2.2 (OK)
qtawesome >=1.2.1                    :  1.2.1 (OK)
qtconsole >=5.4.0;<5.5.0             :  5.4.0 (OK)
qtpy >=2.1.0                         :  2.2.1 (OK)
rtree >=0.9.7                        :  1.0.1 (OK)
setuptools >=49.6.0                  :  65.5.1 (OK)
sphinx >=0.6.6                       :  5.3.0 (OK)
spyder_kernels >=2.4.0;<2.5.0        :  2.4.0 (OK)
textdistance >=4.2.0                 :  4.5.0 (OK)
three_merge >=0.1.1                  :  0.1.1 (OK)
watchdog                             :  2.1.9 (OK)
zmq >=22.1.0                         :  24.0.1 (OK)

# Optional:
cython >=0.21                        :  0.29.32 (OK)
matplotlib >=3.0.0                   :  3.6.2 (OK)
numpy >=1.7                          :  1.22.4 (OK)
pandas >=1.1.1                       :  1.5.1 (OK)
scipy >=0.17.0                       :  1.9.3 (OK)
sympy >=0.7.3                        :  1.11.1 (OK)

# Spyder plugins:
spyder_terminal.terminalplugin 1.2.2 :  1.2.2 (OK)

```



Discussion:
Did you install `spyder-kernels` in the environment you are attempting to use, `paddle3.8.13`? For `Spyder 5.4.x` you need `spyder-kernels 2.4.x`, which is currently *not* available on Anaconda default channel - so you have to use `conda-forge`. I'm not sure how you have setup conda, but to use conda-forge channel:

    conda create -n paddle3.8.13 -c conda-forge python=3.8.13 spyder-kernels=2.4

or if you already installed python/packages in that env with conda-forge

    conda install -c conda-forge spyder-kernels 

It's best not to mix channels within a conda environment.

Also see https://docs.spyder-ide.org/current/faq.html#using-packages-installer
> Did you install spyder-kernels in the environment you are attempting to use, paddle3.8.13?

That's correct @rhkarls, but in PR #19646 I tried to improve the situation by showing the "missing Spyder-kernels" error message when the selected interpreter doesn't have that package.

I added a test for this but only for Linux (because it was easier), but perhaps it's not working for Windows. @dalthviz, could you check if that's not working on Windows, both for the installer and conda? For that, you need to go to `Preferences > Main Interpreter`, select one without Spyder-kernels, go to the IPython console and restart the kernel of the current one.
I was able to reproduce this (both with conda and with the standalone installer on Windows):

![image](https://user-images.githubusercontent.com/16781833/201412812-5802bf51-f3a6-4ca9-ae67-b0508d3af453.png)

![image](https://user-images.githubusercontent.com/16781833/201413419-0c56b42b-a5b9-4b1b-b505-a6904efdeee6.png)

I guess we should could merge #20024 with this one since the error is not related with the way of installation but the OS support to restart kernels on envs without `spyder-kernels` installed on Windows?

Ok, thanks @dalthviz. Will look into it.

Resolving patch:
diff --git a/spyder/plugins/ipythonconsole/widgets/client.py b/spyder/plugins/ipythonconsole/widgets/client.py
--- a/spyder/plugins/ipythonconsole/widgets/client.py
+++ b/spyder/plugins/ipythonconsole/widgets/client.py
@@ -833,38 +833,32 @@ def has_spyder_kernels(self):
                 interpreter=pyexec,
                 version=SPYDER_KERNELS_VERSION)
 
-            if (
-                not has_spyder_kernels
-                # This is necessary to show this message for some tests and not
-                # do it for others.
-                and os.environ.get('SPY_TEST_SHOW_RESTART_MESSAGE')
-            ):
-                self.show_kernel_error(
-                    _("The Python environment or installation whose "
-                      "interpreter is located at"
-                      "<pre>"
-                      "    <tt>{0}</tt>"
-                      "</pre>"
-                      "doesn't have the <tt>spyder-kernels</tt> module or the "
-                      "right version of it installed ({1}). "
-                      "Without this module is not possible for Spyder to "
-                      "create a console for you.<br><br>"
-                      "You can install it by activating your environment (if "
-                      "necessary) and then running in a system terminal:"
-                      "<pre>"
-                      "    <tt>{2}</tt>"
-                      "</pre>"
-                      "or"
-                      "<pre>"
-                      "    <tt>{3}</tt>"
-                      "</pre>").format(
-                          pyexec,
-                          SPYDER_KERNELS_VERSION_MSG,
-                          SPYDER_KERNELS_CONDA,
-                          SPYDER_KERNELS_PIP
-                      )
+            msg = _(
+                "The Python environment or installation whose interpreter is "
+                "located at"
+                "<pre>"
+                "    <tt>{0}</tt>"
+                "</pre>"
+                "doesn't have the <tt>spyder-kernels</tt> module or the right "
+                "version of it installed ({1}). Without this module is not "
+                "possible for Spyder to create a console for you.<br><br>"
+                "You can install it by activating your environment first (if "
+                "necessary) and then running in a system terminal:"
+                "<pre>"
+                "    <tt>{2}</tt>"
+                "</pre>"
+                "or"
+                "<pre>"
+                "    <tt>{3}</tt>"
+                "</pre>").format(
+                    pyexec,
+                    SPYDER_KERNELS_VERSION_MSG,
+                    SPYDER_KERNELS_CONDA,
+                    SPYDER_KERNELS_PIP
                 )
 
+            if not has_spyder_kernels:
+                self.show_kernel_error(msg)
                 return False
             else:
                 return True
diff --git a/spyder/plugins/ipythonconsole/widgets/shell.py b/spyder/plugins/ipythonconsole/widgets/shell.py
--- a/spyder/plugins/ipythonconsole/widgets/shell.py
+++ b/spyder/plugins/ipythonconsole/widgets/shell.py
@@ -264,8 +264,9 @@ def interrupt_kernel(self):
             super(ShellWidget, self).interrupt_kernel()
         else:
             self._append_html(
-                _("The kernel appears to be dead, so it can't be interrupted. "
-                  "Please open a new console to keep working.")
+                _("<br><br>The kernel appears to be dead, so it can't be "
+                  "interrupted. Please open a new console to keep "
+                  "working.<br>")
             )
 
     def execute(self, source=None, hidden=False, interactive=False):


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
@@ -44,6 +44,7 @@
     running_in_ci, running_in_ci_with_conda)
 from spyder.config.gui import get_color_scheme
 from spyder.config.manager import CONF
+from spyder.config.utils import is_anaconda
 from spyder.py3compat import PY2, to_text_string
 from spyder.plugins.help.tests.test_plugin import check_text
 from spyder.plugins.help.utils.sphinxify import CSS_PATH
@@ -51,7 +52,7 @@
 from spyder.plugins.ipythonconsole.utils.style import create_style_class
 from spyder.plugins.ipythonconsole.widgets import ClientWidget
 from spyder.utils.programs import get_temp_dir
-from spyder.utils.conda import is_conda_env
+from spyder.utils.conda import get_conda_root_prefix
 
 
 # =============================================================================
@@ -78,8 +79,11 @@ def get_console_background_color(style_sheet):
     return background_color
 
 
-def get_conda_test_env(test_env_name=u'spytest-ž'):
-    """Return the full prefix path of the given `test_env_name`."""
+def get_conda_test_env(test_env_name='spytest-ž'):
+    """
+    Return the full prefix path of the given `test_env_name` and its
+    executable.
+    """
     if 'envs' in sys.prefix:
         root_prefix = os.path.dirname(os.path.dirname(sys.prefix))
     else:
@@ -92,7 +96,7 @@ def get_conda_test_env(test_env_name=u'spytest-ž'):
     else:
         test_env_executable = os.path.join(test_env_prefix, 'bin', 'python')
 
-    return test_env_executable
+    return (test_env_prefix, test_env_executable)
 
 
 # =============================================================================
@@ -196,7 +200,7 @@ def __getattr__(self, attr):
     if test_environment_interpreter:
         configuration.set('main_interpreter', 'default', False)
         configuration.set(
-            'main_interpreter', 'executable', get_conda_test_env())
+            'main_interpreter', 'executable', get_conda_test_env()[1])
     else:
         configuration.set('main_interpreter', 'default', True)
         configuration.set('main_interpreter', 'executable', '')
@@ -1657,6 +1661,8 @@ def test_calltip(ipyconsole, qtbot):
 @flaky(max_runs=3)
 @pytest.mark.order(1)
 @pytest.mark.test_environment_interpreter
+@pytest.mark.skipif(not is_anaconda(), reason='Only works with Anaconda')
+@pytest.mark.skipif(not running_in_ci(), reason='Only works on CIs')
 def test_conda_env_activation(ipyconsole, qtbot):
     """
     Test that the conda environment associated with an external interpreter
@@ -1668,12 +1674,12 @@ def test_conda_env_activation(ipyconsole, qtbot):
     # Get conda activation environment variable
     with qtbot.waitSignal(shell.executed):
         shell.execute(
-            "import os; conda_prefix = os.environ.get('CONDA_PREFIX')")
+            "import os; conda_prefix = os.environ.get('CONDA_PREFIX')"
+        )
 
-    expected_output = get_conda_test_env().replace('\\', '/')
-    if is_conda_env(expected_output):
-        output = shell.get_value('conda_prefix').replace('\\', '/')
-        assert expected_output == output
+    expected_output = get_conda_test_env()[0].replace('\\', '/')
+    output = shell.get_value('conda_prefix').replace('\\', '/')
+    assert expected_output == output
 
 
 @flaky(max_runs=3)
@@ -2438,8 +2444,7 @@ def test_run_script(ipyconsole, qtbot, tmp_path):
 
 
 @pytest.mark.skipif(
-    not sys.platform.startswith('linux'),
-    reason="Only runs on Linux")
+    not is_anaconda(), reason="Only works with Anaconda")
 def test_show_spyder_kernels_error_on_restart(ipyconsole, qtbot):
     """Test that we show Spyder-kernels error message on restarts."""
     # Wait until the window is fully up
@@ -2449,11 +2454,13 @@ def test_show_spyder_kernels_error_on_restart(ipyconsole, qtbot):
 
     # Point to an interpreter without Spyder-kernels
     ipyconsole.set_conf('default', False, section='main_interpreter')
-    ipyconsole.set_conf('executable', '/usr/bin/python3',
-                        section='main_interpreter')
+    if os.name == 'nt':
+        pyexec = osp.join(get_conda_root_prefix(), 'python.exe')
+    else:
+        pyexec = osp.join(get_conda_root_prefix(), 'bin', 'python')
+    ipyconsole.set_conf('executable', pyexec, section='main_interpreter')
 
     # Restart kernel
-    os.environ['SPY_TEST_SHOW_RESTART_MESSAGE'] = 'true'
     ipyconsole.restart_kernel()
 
     # Assert we show a kernel error
@@ -2467,7 +2474,7 @@ def test_show_spyder_kernels_error_on_restart(ipyconsole, qtbot):
         timeout=6000
     )
 
-    # To check kernel error visually
+    # To check the kernel error visually
     qtbot.wait(500)
 
     # Check kernel related actions are disabled