I have some Python code example I'd like to share that should do something different if executed in the terminal Python / IPython or in the IPython notebook.
How can I check from my Python code if it's running in the IPython notebook?
I have some Python code example I'd like to share that should do something different if executed in the terminal Python / IPython or in the IPython notebook.
How can I check from my Python code if it's running in the IPython notebook?
The question is what do you want execute differently.
We do our best in IPython prevent the kernel from knowing to which kind of frontend is connected, and actually you can even have a kernel connected to many differents frontends at the same time. Even if you can take a peek at the type of stderr/out
to know wether you are in a ZMQ kernel or not, it does not guaranties you of what you have on the other side. You could even have no frontends at all.
You should probably write your code in a frontend independent manner, but if you want to display different things, you can use the rich display system (link pinned to version 4.x of IPython) to display different things depending on the frontend, but the frontend will choose, not the library.
\x1b[A
(move up), so it's not possible to print nested bars. No problem with ipywidgets, we can use native Jupyter widgets to display progress bars. But then we have two different means of displaying a progress bar, and an application might want to know what is the display environment in order to adapt and print the compatible bar. –
Sannyasi %matplotlib inline
when it acts as a notebook, but not in a terminal, since that is not needed. –
Susurration display(HTML(...))
in my script. When run from a notebook it works. When run as a normal Python script it just prints <IPython.core.display.HTML object>
which is useless, so I need to manually open a browser to display the HTML code, or convert the HTML to something that I can print in the terminal. –
Budding startup.ipy
. When in the terminal IPython, for convenience I like to have a few packages pre-imported. When in a notebook, that is considered bad style, and not necessary because I can put the imports in the first cell, not having to type them again and again. –
Troxler display()
from the command line. –
Sarita The following worked for my needs:
get_ipython().__class__.__name__
It returns 'TerminalInteractiveShell'
on a terminal IPython, 'ZMQInteractiveShell'
on Jupyter (notebook AND qtconsole) and fails (NameError
) on a regular Python interpreter. The function get_ipython()
is available on the global namespace by default when IPython is started.
Wrapping it in a simple function:
def is_notebook() -> bool:
try:
shell = get_ipython().__class__.__name__
if shell == 'ZMQInteractiveShell':
return True # Jupyter notebook or qtconsole
elif shell == 'TerminalInteractiveShell':
return False # Terminal running IPython
else:
return False # Other type (?)
except NameError:
return False # Probably standard Python interpreter
The above was tested with Python 3.5.2, IPython 5.1.0 and Jupyter 4.2.1 on macOS 10.12 and Ubuntu 14.04.4 LTS
EDIT: This still works fine in 2022 on newer Python/IPython/Jupyter/OS versions
jupyter console
, unfortunately get_ipython()
returns an instance of ZMQInteractiveShell
also –
Emplace get_ipython().__class__.__module__ == "google.colab._shell"
–
Calctufa test.py
then run from test import isnotebook; print(isnotebook())
in a Jupyter Notebook, it prints True
. (Tested on Notebook server versions 5.2.1 and 6.0.1.) –
Sugar def we_are_in_jupyter()
:) imgur.com/9mx9COw You've made it to the brain of the AI –
Eam You can check whether python is in interactive mode with the following snippet [1]:
def is_interactive():
import __main__ as main
return not hasattr(main, '__file__')
I have found this method very useful because I do a lot of prototyping in the notebook. For testing purposes, I use default parameters. Otherwise, I read the parameters from sys.argv
.
from sys import argv
if is_interactive():
params = [<list of default parameters>]
else:
params = argv[1:]
Following the implementation of autonotebook
, you can tell whether you are in a notebook using the following code.
def in_notebook():
try:
from IPython import get_ipython
if 'IPKernelApp' not in get_ipython().config: # pragma: no cover
return False
except ImportError:
return False
except AttributeError:
return False
return True
is_interactive()
does not distinguish between notebook and console. –
Haya %run
from ipython is non-interactive. You could argue it should be, but it is still a gotcha. –
Dennisedennison is_interactive
) seems to me to be basically irrelevant to the question. It's also of dubious correctness; as @Quintessa points out, it counts anything run using python -c
as being in "interactive" mode even though this isn't true. I don't want to do it myself since it's not my answer, but I think this would be improved by simply deleting the entire first half of the answer. –
Sugar get_ipython
will returns None
when run from an ordinary python shell or a running a script, so this code needs to guard against that case. –
Inez Python versions 3.12, 3.11 do not have module __main__
. –
Needlecraft To check if you're in a notebook, which can be important e.g. when determining what sort of progressbar to use, this worked for me:
def in_ipynb():
try:
cfg = get_ipython().config
if cfg['IPKernelApp']['parent_appname'] == 'ipython-notebook':
return True
else:
return False
except NameError:
return False
cfg['IPKernelApp']['parent_appname']
is a IPython.config.loader.LazyConfigValue
, which does not compare to True
with "iypthon-notebook"
–
Counteroffensive IPython.kernel.zmq.zmqshell.ZMQInteractiveShell
instance in ipynb (Jupyter) and an IPython.terminal.interactiveshell.TerminalInteractiveShell
in a terminal REPL, in case you need to differentiate between notebooks and terminal/consoles (which affects plotting). –
Gambeson try
block with: return str(type(get_ipython())) == "<class 'ipykernel.zmqshell.ZMQInteractiveShell'>"
–
Campman shell='PyDevTerminalInteractiveShell'
when inspecting the class name. –
Martz Recently I encountered a bug in Jupyter notebook which needs a workaround, and I wanted to do this without loosing functionality in other shells. I realized that keflavich's solution does not work in this case, because get_ipython()
is available only directly from the notebook, and not from imported modules. So I found a way to detect from my module whether it is imported and used from a Jupyter notebook or not:
import sys
def in_notebook():
"""
Returns ``True`` if the module is running in IPython kernel,
``False`` if in IPython shell or other Python shell.
"""
return 'ipykernel' in sys.modules
# later I found out this:
def ipython_info():
ip = False
if 'ipykernel' in sys.modules:
ip = 'notebook'
elif 'IPython' in sys.modules:
ip = 'terminal'
return ip
Comments are appreciated if this is robust enough.
Similar way it is possible to get some info about the client, and IPython version as well:
import sys
if 'ipykernel' in sys.modules:
ip = sys.modules['ipykernel']
ip_version = ip.version_info
ip_client = ip.write_connection_file.__module__.split('.')[0]
# and this might be useful too:
ip_version = IPython.utils.sysinfo.get_sys_info()['ipython_version']
'Ipython' in sys.modules
evaluates to False
. Perhaps you mean 'IPython' in sys.modules
? This is True
in my Jupyter environment. The sys.modules
dictionary also doesn't include the 'ipykernel'
key - when running inside a notebook. –
Gram ipykernel
, which results in this logic returning a false positive (e.g. Weights and Biases package). So it will work most of the time, but not always. –
Bathhouse Tested for python 3.7.3
CPython implementations have the name __builtins__
available as part of their globals which btw. can be retrieved by the function globals().
If a script is running in an Ipython environment then __IPYTHON__
should be an attribute of __builtins__
.
The code below therefore returns True
if run under Ipython or else it gives False
hasattr(__builtins__,'__IPYTHON__')
import builtins
though and check hasattr(builtins, "__IPYTHON__")
, since __builtins__
is an implementation detail that could change. –
Chemosynthesis NameError: name '__IPYTHON__' is not defined
–
Boeotia pytest
but I will continue using it until one of the other tricks is proven best. Seems like a great article for someone to summarize and test against all the versions of environments for the community! –
Idou import builtins
and hasattr(builtins, "__IPYTHON__")
for this to work; __builtins__
returned False for IPython too. –
Cuthbert The question is what do you want execute differently.
We do our best in IPython prevent the kernel from knowing to which kind of frontend is connected, and actually you can even have a kernel connected to many differents frontends at the same time. Even if you can take a peek at the type of stderr/out
to know wether you are in a ZMQ kernel or not, it does not guaranties you of what you have on the other side. You could even have no frontends at all.
You should probably write your code in a frontend independent manner, but if you want to display different things, you can use the rich display system (link pinned to version 4.x of IPython) to display different things depending on the frontend, but the frontend will choose, not the library.
\x1b[A
(move up), so it's not possible to print nested bars. No problem with ipywidgets, we can use native Jupyter widgets to display progress bars. But then we have two different means of displaying a progress bar, and an application might want to know what is the display environment in order to adapt and print the compatible bar. –
Sannyasi %matplotlib inline
when it acts as a notebook, but not in a terminal, since that is not needed. –
Susurration display(HTML(...))
in my script. When run from a notebook it works. When run as a normal Python script it just prints <IPython.core.display.HTML object>
which is useless, so I need to manually open a browser to display the HTML code, or convert the HTML to something that I can print in the terminal. –
Budding startup.ipy
. When in the terminal IPython, for convenience I like to have a few packages pre-imported. When in a notebook, that is considered bad style, and not necessary because I can put the imports in the first cell, not having to type them again and again. –
Troxler display()
from the command line. –
Sarita All you have to do is to place these two cells at the beginning of your notebook:
Cell 1: (marked as "code"):
is_notebook = True
Cell 2: (marked as "Raw NBConvert"):
is_notebook = False
The first cell will always be executed, but the second cell will only be executed when you export the notebook as a Python script.
Later, you can check:
if is_notebook:
notebook_code()
else:
script_code()
Hope this helps.
As far as I know, Here has 3 kinds of ipython that used ipykernel
ipython qtconsole
("qtipython" for short)use 'spyder' in sys.modules
can distinguish spyder
but for qtipython and jn are hard to distinguish because
they have same sys.modules
and same IPython config:get_ipython().config
I find a different between qtipython and jn:
first run os.getpid()
in IPython shell to get the pid number
then run ps -ef|grep [pid number]
my qtipython pid is 8699
yanglei 8699 8693 4 20:31 ? 00:00:01 /home/yanglei/miniconda2/envs/py3/bin/python -m ipykernel_launcher -f /run/user/1000/jupyter/kernel-8693.json
my jn pid is 8832
yanglei 8832 9788 13 20:32 ? 00:00:01 /home/yanglei/miniconda2/bin/python -m ipykernel_launcher -f /run/user/1000/jupyter/kernel-ccb962ec-3cd3-4008-a4b7-805a79576b1b.json
the different of qtipython and jn is the ipython's json name, jn's json name are longer than qtipython's
so, we can auto-detect all Python Environment using the following code:
import sys,os
def jupyterNotebookOrQtConsole():
env = 'Unknow'
cmd = 'ps -ef'
try:
with os.popen(cmd) as stream:
if not py2:
stream = stream._stream
s = stream.read()
pid = os.getpid()
ls = list(filter(lambda l:'jupyter' in l and str(pid) in l.split(' '), s.split('\n')))
if len(ls) == 1:
l = ls[0]
import re
pa = re.compile(r'kernel-([-a-z0-9]*)\.json')
rs = pa.findall(l)
if len(rs):
r = rs[0]
if len(r)<12:
env = 'qtipython'
else :
env = 'jn'
return env
except:
return env
pyv = sys.version_info.major
py3 = (pyv == 3)
py2 = (pyv == 2)
class pyi():
'''
python info
plt : Bool
mean plt avaliable
env :
belong [cmd, cmdipython, qtipython, spyder, jn]
'''
pid = os.getpid()
gui = 'ipykernel' in sys.modules
cmdipython = 'IPython' in sys.modules and not gui
ipython = cmdipython or gui
spyder = 'spyder' in sys.modules
if gui:
env = 'spyder' if spyder else jupyterNotebookOrQtConsole()
else:
env = 'cmdipython' if ipython else 'cmd'
cmd = not ipython
qtipython = env == 'qtipython'
jn = env == 'jn'
plt = gui or 'DISPLAY' in os.environ
print('Python Envronment is %s'%pyi.env)
The source code is here: Detection Python Environment, Especially distinguish Spyder, Jupyter notebook, Qtconsole.py
ps
command. That's bad. Windows isn't POSIX-compatible unless you're running under the Windows Subsystem for Linux (WSL), which means this fails on the world's most popular platform. Woops. –
Exhibition The following captures the cases of https://mcmap.net/q/156795/-how-can-i-check-if-code-is-executed-in-the-ipython-notebook without needing to parse the output of ps
def pythonshell():
"""Determine python shell
pythonshell() returns
'shell' (started python on command line using "python")
'ipython' (started ipython on command line using "ipython")
'ipython-notebook' (e.g., running in Spyder or started with "ipython qtconsole")
'jupyter-notebook' (running in a Jupyter notebook)
See also https://stackoverflow.com/a/37661854
"""
import os
env = os.environ
shell = 'shell'
program = os.path.basename(env['_'])
if 'jupyter-notebook' in program:
shell = 'jupyter-notebook'
elif 'JPY_PARENT_PID' in env or 'ipython' in program:
shell = 'ipython'
if 'JPY_PARENT_PID' in env:
shell = 'ipython-notebook'
return shell
jupyter
whether it is a jupyter console
, jupyter qtconsole
, or jupyter notebook
. –
Joe I would recommend avoiding to detect specific frontend because there are too many of them. Instead you can just test if you are running from within iPython environment:
def is_running_from_ipython():
from IPython import get_ipython
return get_ipython() is not None
Above will return False
if you are invoking running_from_ipython
from usual python command line. When you invoke it from Jupyter Notebook, JupyterHub, iPython shell, Google Colab etc then it will return True
.
get_ipython()
returns <ipykernel.zmqshell.ZMQInteractiveShell at 0x7f750ba94320>
. –
Strake get_ipython() is not None
returning True
. –
Martz A very simple and efficient solution is to check if the top of the call stack refers to IPython environment, as follows:
import traceback
def is_in_notebook():
rstk = traceback.extract_stack(limit=1)[0]
return rstk[0].startswith("<ipython")
This code works for both Python 2 and 3, on IPython or Jupyter, with no need to check, set or change the environment.
I am using Django Shell Plus to launch IPython, and I wanted to make 'running in notebook' available as a Django settings value. get_ipython()
is not available when loading settings, so I use this (which is not bulletproof, but good enough for the local development environments it's used in):
import sys
if '--notebook' in sys.argv:
ENVIRONMENT = "notebook"
else:
ENVIRONMENT = "dev"
Assuming you have control of the Jupyter Notebook you could:
set an environment value in a cell that uses this as a flag in your code. Place a unique comment in that cell (or all cells you want to exclude)
# exclude_from_export
%set_env is_jupyter=1
Export the notebook as a python script to be used in a different context. The export would exclude the commented cell(s) and subsequently the code that sets the environment value. Note: replace your_notebook.ipynb with the name of your actual notebook file.
jupyter nbconvert --to script --RegexRemovePreprocessor.patterns="['^# exclude_from_export']" your_notebook.ipynb
This will generate a file that will not have the jupyter environment flag set allowing for code that uses it to deterministically execute.
How about something like this:
import sys
inJupyter = sys.argv[-1].endswith('json')
print(inJupyter);
"json"
!= the current Python process is Jupyter. Those two conditions are only tangentially correlated at best. Good luck resolving false positives with a naively brute-force detection scheme like this. –
Exhibition The following would let one know where the python code is being run... be it in Jupyter standalone, Python standalone, Spyder, VSCode or Jupyter notbeook within VSCode.
import os
import IPython as ipy
# add string sources only
sources = str(os.environ.keys()) + \
ipy.get_ipython().__class__.__name__
# make pattern of unique keys
checks = {'SPYDER': 'Spyder', 'QTIPYTHON': 'qt IPython', 'VSCODE':
'VS Code', 'ZMQINTERACTIVEshell': 'Jupyter', }
results = []
msg = []
for k, v in checks.items():
u = str(k.upper())
if u in sources.upper():
results.append(checks[k])
if not results:
msg.append("Unknown IDE")
else:
msg.append("Program working ")
while results:
msg.append(f"in {results.pop()}")
if results:
msg.append(' with')
print(''.join(msg))
This works:
def is_interactive():
try:
__IPYTHON__
return True
except NameError:
return False
You can try to eval('__IPYTHON__')
, borrowed from pydantic:
def in_ipython() -> bool:
"""
Check whether we're in an ipython environment, including jupyter notebooks.
"""
try:
eval('__IPYTHON__')
except NameError:
return False
else: # pragma: no cover
return True
So far the only solution that worked for me is to check the parent processes using psutil:
import psutil
def runninginJupyterNotebook():
for i in psutil.Process().parent().cmdline():
if "jupyter-notebook" in i:
return True
else:
return False
Or you can set a variable in one line:
RUNNING_IN_JUPYTER = any(["jupyter-notebook" in i for i in psutil.Process().parent().cmdline()])
RUNNING_IN_JUPYTER
is True
if you are running a Jupyter Notebook.
Note that it will be true also if you are running a Colab notebook.
import psutil
def runninginJupyterNotebook():
for i in psutil.Process().parent().cmdline():
if "jupyter-notebook" in i:
return True
else:
return False
Or you can set a variable in one line:
RUNNING_IN_JUPYTER = any([i.endswith("bin/jupyter-notebook") for i in psutil.Process().parent().cmdline()])
get_ipython().__class__.__name__
All the solutions using get_ipython()
work only if you don't care if it is running on a QtConsole.
Credits: https://mcmap.net/q/160107/-get-base-url-of-current-jupyter-server-ipython-is-connected-to
python.exe -c "import psutil as p; T=any([i.endswith('bin/jupyter-notebook') for i in p.Process().parent().cmdline()]);print(T);"
works in powershell, but not running the same in Jupyter. –
Cordierite © 2022 - 2024 — McMap. All rights reserved.