我有一些Python代码示例想要分享,如果在终端Python/IPython或IPython笔记本中执行,应该会执行不同的操作。
如何从我的Python代码中检查它是否在IPython笔记本中运行?
我有一些Python代码示例想要分享,如果在终端Python/IPython或IPython笔记本中执行,应该会执行不同的操作。
如何从我的Python代码中检查它是否在IPython笔记本中运行?
以下方法适用于我的需求:
get_ipython().__class__.__name__
在终端IPython上返回'TerminalInteractiveShell'
,在Jupyter上返回'ZMQInteractiveShell'
(包括notebook和qtconsole),并在普通Python解释器上失败(抛出NameError
)。当启动IPython时,函数get_ipython()
默认情况下在全局命名空间中可用。
将其包装在一个简单的函数中:
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
以上内容是在macOS 10.12和Ubuntu 14.04.4 LTS上使用Python 3.5.2、IPython 5.1.0和Jupyter 4.2.1进行测试的。
编辑:在2022年,使用更新的Python/IPython/Jupyter/操作系统版本仍然可以正常工作。
get_ipython()
返回的实例也是ZMQInteractiveShell
。 - Josh Bodeget_ipython().__class__.__module__ == "google.colab._shell"
- guiferviztest.py
的文件中,然后在 Jupyter Notebook 中运行 from test import isnotebook; print(isnotebook())
,它会打印出 True
。(已在笔记本服务器版本为 5.2.1 和 6.0.1 的情况下进行测试。) - Mark Amerydef we_are_in_jupyter()
时由Github Copilot自动生成的 :) https://imgur.com/9mx9COw 你已经到达了AI的大脑。 - Jules G.M.def is_interactive():
import __main__ as main
return not hasattr(main, '__file__')
我发现这种方法非常有用,因为我在笔记本上进行了很多原型制作。为了测试目的,我使用默认参数。否则,我从 sys.argv
读取参数。
from sys import argv
if is_interactive():
params = [<list of default parameters>]
else:
params = argv[1:]
在实施了 autonotebook
之后,您可以使用以下代码来确定是否处于笔记本中。
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
import __main__ as main
return not hasattr(main, '__file__')
print is_interactive()"
True
- marscheris_interactive()
无法区分笔记本和控制台。 - krock%run
命令是非交互式的。你可以认为它应该是交互式的,但这仍然是一个陷阱。 - dirkjotis_interactive
的前半部分对于问题来说似乎基本上无关紧要。它还存在可疑的正确性; 正如@marscher指出的那样,即使这不是真的,它也会将使用python -c
运行的任何东西都计算为处于“交互”模式。我不想自己做这件事,因为这不是我的回答,但我认为通过简单删除答案的整个前半部分可以使其更好。 - Mark Ameryget_ipython
将返回None
,因此此代码需要防范这种情况。 - Lucas Wiman如果您想检查当前是否在notebook中,这可能很重要,例如在确定使用哪种进度条时,可以使用以下方法:
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']
是一个IPython.config.loader.LazyConfigValue
,它与“iypthon-notebook”不相等。 - DuxIPython.kernel.zmq.zmqshell.ZMQInteractiveShell
实例,在终端REPL中则返回一个IPython.terminal.interactiveshell.TerminalInteractiveShell
实例。如果你需要区分笔记本和终端/控制台(这会影响绘图),这就很有用了。 - hobstry
块内部替换为:return str(type(get_ipython())) == "<class'ipykernel.zmqshell.ZMQInteractiveShell'>"
。 - user2561747shell='PyDevTerminalInteractiveShell'
。 - hlongmore最近我在Jupyter笔记本中遇到了一个错误,需要一个解决方法,而且我希望在不影响其他shell的功能的情况下完成。我意识到keflavich的解决方案在这种情况下不起作用,因为get_ipython()
只能直接从笔记本中使用,而不能从导入的模块中使用。所以我找到了一种方法来检测我的模块是否被导入并且是在Jupyter笔记本中使用的:
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
如果这足够健壮,欢迎留下评论。
同样的方法也可以获取有关客户端和IPython版本的一些信息:
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
的评估结果为False
。也许你的意思是'IPython' in sys.modules
?在我的Jupyter环境中,这个表达式的值为True
。当在笔记本中运行时,sys.modules
字典也不包括'ipykernel'
键。 - maxschlepzigipykernel
,这会导致此逻辑返回错误结果(例如Weights and Biases软件包)。因此,它将在大多数情况下工作,但并非总是如此。 - David Gilbertson测试过适用于Python 3.7.3
CPython实现中将__builtins__
作为全局变量之一,可以通过函数globals()检索。如果脚本在Ipython环境中运行,则__IPYTHON__
应该是__builtins__
的属性。因此,以下代码在Ipython环境下运行时返回True
,否则返回False
hasattr(__builtins__,'__IPYTHON__')
stderr / out
类型以知道您是否在ZMQ内核中,这并不能保证您拥有什么。您甚至可能没有任何前端。\x1b[A
(向上移动),因此无法打印嵌套的进度条。使用ipywidgets没有问题,我们可以使用本地Jupyter小部件来显示进度条。但是现在我们有了两种不同的进度条显示方式,应用程序可能想要知道当前显示环境,以便适应并打印兼容的进度条。 - gaborous%matplotlib inline
,但在终端中不需要这样做。 - Ciprian Tomoiagăstartup.ipy
。在终端IPython中,为了方便起见,我喜欢预先导入一些包。但在笔记本中,这被认为是不良的风格,并且不必要,因为我可以把导入放在第一个单元格中,而不需要一遍又一遍地输入它们。 - A. Donda您只需要将这两个单元格放在笔记本的开头:
单元格 1: (标记为“代码”):
is_notebook = True
单元格2:(标记为“原始NBConvert”):
is_notebook = False
if is_notebook:
notebook_code()
else:
script_code()
一个非常简单和有效的解决方案是检查调用堆栈的顶部是否指向IPython环境,如下所示:
import traceback
def is_in_notebook():
rstk = traceback.extract_stack(limit=1)[0]
return rstk[0].startswith("<ipython")
ipykernel
的ipython:
ipython qtconsole
(简称“qtipython”)'spyder' in sys.modules
可以区分 spyder,但是对于 qtipython 和 jn,很难区分,因为它们具有相同的sys.modules
和相同的 IPython 配置:get_ipython().config
。os.getpid()
来获取 pid 号码,ps -ef|grep [pid number]
。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
qtipython和jn的区别在于IPython的JSON名称,jn的JSON名称比qtipython的长。
因此,我们可以使用以下代码自动检测所有Python环境:
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)
ps
命令。那很糟糕。除非你在运行Windows子系统Linux(WSL)下,否则Windows不兼容POSIX,这意味着它在全球最流行的平台上失败了。哎呀。 - Cecil Curryps
的输出。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://dev59.com/AWUp5IYBdhLWcg3wPFz_#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
显示它是 jupyter console
、jupyter qtconsole
还是 jupyter notebook
。 - Luke Davis