如何检查代码是否在 IPython 笔记本中执行?
- 2025-03-13 09:06:00
- admin 原创
- 88
问题描述:
我有一些 Python 代码示例想要分享,如果在终端 Python / IPython 或 IPython 笔记本中执行,应该会做一些不同的事情。
如何检查我的 Python 代码是否在 IPython 笔记本中运行?
解决方案 1:
以下满足了我的需求:
get_ipython().__class__.__name__
'TerminalInteractiveShell'
它在终端 IPython'ZMQInteractiveShell'
和 Jupyter(notebook 和 qtconsole)上返回,并在常规 Python 解释器上失败()。启动 IPython 时,NameError
该函数默认在全局命名空间中可用。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/OS 版本上,此功能仍可正常运行
解决方案 2:
你可以使用以下代码片段[1]检查python是否处于交互模式:
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
解决方案 3:
要检查您是否在笔记本中,这可能很重要,例如在确定使用哪种进度条时,这对我有用:
def in_ipynb():
try:
cfg = get_ipython().config
if cfg['IPKernelApp']['parent_appname'] == 'ipython-notebook':
return True
else:
return False
except NameError:
return False
解决方案 4:
最近我在 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']
解决方案 5:
针对 Python 3.7.3 进行了测试
CPython 实现将名称__builtins__
作为全局变量的一部分,顺便说一句,可以通过函数 globals() 检索。
如果脚本在 Ipython 环境中运行,则__IPYTHON__
应该是 的一个属性__builtins__
。
因此,如果在 Ipython 下运行,则下面的代码将返回,True
否则将给出False
hasattr(__builtins__,'__IPYTHON__')
解决方案 6:
问题是你想以不同的方式执行什么。
在 IPython 中,我们尽最大努力防止内核知道连接到哪种前端,实际上,您甚至可以让内核同时连接到许多不同的前端。即使您可以查看类型stderr/out
以了解您是否在 ZMQ 内核中,也不能保证您在另一端拥有什么。您甚至可能根本没有前端。
您可能应该以独立于前端的方式编写代码,但如果您想显示不同的东西,您可以使用丰富的显示系统(链接固定到 IPython 4.x 版本)根据前端显示不同的东西,但前端会选择,而不是库。
解决方案 7:
您所要做的就是将这两个单元格放在笔记本的开头:
单元格1:(标记为“代码”):
is_notebook = True
单元格 2:(标记为“Raw NBConvert”):
is_notebook = False
第一个单元将始终被执行,但仅当您将笔记本导出为 Python 脚本时才会执行第二个单元。
稍后,您可以检查:
if is_notebook:
notebook_code()
else:
script_code()
希望这有帮助。
解决方案 8:
下面捕获了https://stackoverflow.com/a/50234148/1491619的情况,而无需解析输出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
解决方案 9:
我建议避免检测特定的前端,因为它们太多了。相反,你可以测试是否在 iPython 环境中运行:
def is_running_from_ipython():
from IPython import get_ipython
return get_ipython() is not None
False
如果您从通常的 Python 命令行调用,则将返回上述内容running_from_ipython
。当您从 Jupyter Notebook、JupyterHub、iPython shell、Google Colab 等调用它时,它将返回True
。
解决方案 10:
一个非常简单有效的解决方案是检查调用堆栈的顶部是否引用 IPython 环境,如下所示:
import traceback
def is_in_notebook():
rstk = traceback.extract_stack(limit=1)[0]
return rstk[0].startswith("<ipython")
该代码适用于 IPython 或 Jupyter 上的 Python 2 和 3,无需检查、设置或更改环境。
解决方案 11:
据我所知,这里有 3 种 ipythonipykernel
ipython qtconsole
(简称“qtipython”)spyder 中的 IPython(简称“spyder”)
jupyter notebook 中的 IPython(简称“jn”)
使用'spyder' in sys.modules
可以区分spyder
但对于 qtipython 和 jn 来说很难区分,因为
它们有相同sys.modules
的 IPython 配置:get_ipython().config
我发现 qtipython 和 jn 之间的不同之处:
首先os.getpid()
在 IPython shell 中运行以获取 pid 编号
然后运行ps -ef|grep [pid number]
我的 qtipython pid 是 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
我的 jn pid 是 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('
')))
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)
源代码在这里:检测Python环境,特别区分Spyder,Jupyter notebook,Qtconsole.py
解决方案 12:
我正在使用 Django Shell Plus 启动 IPython,并且我想将“在笔记本中运行”作为 Django 设置值。get_ipython()
在加载设置时不可用,因此我使用这个(虽然不是万无一失的,但对于它所使用的本地开发环境来说已经足够好了):
import sys
if '--notebook' in sys.argv:
ENVIRONMENT = "notebook"
else:
ENVIRONMENT = "dev"
解决方案 13:
假设你可以控制 Jupyter Notebook,你可以:
在单元格中设置环境值,并将其用作代码中的标志。在该单元格中放置一个唯一的注释(或要排除的所有单元格)
排除从导出
%set_env is_jupyter = 1
将笔记本导出为 Python 脚本,以便在不同的上下文中使用。导出将排除注释的单元格,随后排除设置环境值的代码。注意:将your_notebook.ipynb替换为实际笔记本文件的名称。
jupyter nbconvert --to 脚本 --RegexRemovePreprocessor.patterns="['^# exclude_from_export']" your_notebook.ipynb
这将生成一个没有设置 jupyter 环境标志的文件,从而允许使用它的代码确定性地执行。
解决方案 14:
这有效:
def is_interactive():
try:
__IPYTHON__
return True
except NameError:
return False
解决方案 15:
那么像这样的事情怎么样:
import sys
inJupyter = sys.argv[-1].endswith('json')
print(inJupyter);
解决方案 16:
以下内容将让人们知道 Python 代码在哪里运行...是在 Jupyter 独立版、Python 独立版、Spyder、VSCode 还是 Jupyter 而不是 VSCode 中。
import os
import IPython as ipy
# add string sources only
sources = str(os.environ.keys()) + \n 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))
解决方案 17:
我想使用一种在未安装 ipython 时也能正常工作的解决方案,我想出了这个 1(?) 行程序,我发现它非常有用。
这种方法不需要任何救援。
解决方案
if locals().get('get_ipython', lambda: None).__class__.__name__ == 'TerminalInteractiveShell':
print('ipython interactive shell detected!')
解释
如果安装并加载了 ipython,那么该函数将位于
locals()
.
locals().get('get_ipython')
# -> <bound method InteractiveShell.get_ipython of
# <IPython.terminal.interactiveshell.TerminalInteractiveShell object at 0x107164a70>>
然后我们可以调用这个函数
get_ipython()
,并获取“交互式 shell 实例”的类名。
locals().get('get_ipython')()
# -> <IPython.terminal.interactiveshell.TerminalInteractiveShell at 0x107164a70>
如果
get_ipython
不是函数形式,那么我们可以返回一个空的 lambda 函数来进行类名比较
在 ipython 会话中:
locals().get('get_ipython', lambda: None).__class__.__name__
# -> 'TerminalInteractiveShell'
不在 ipython 会话中:
☯ ~ python3 -c "print(locals().get('get_ipython', lambda: None)().__class__.__name__)"
# -> NoneType
解决方案 18:
你可以尝试eval('__IPYTHON__')
,借用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
解决方案 19:
检查父进程
到目前为止,对我有用的唯一解决方案是使用psutil检查父进程:
import psutil
def runninginJupyterNotebook():
for i in psutil.Process().parent().cmdline():
if "jupyter-notebook" in i:
return True
else:
return False
或者您可以在一行中设置一个变量:
RUNNING_IN_JUPYTER = any(["jupyter-notebook" in i for i in psutil.Process().parent().cmdline()])
RUNNING_IN_JUPYTER
如果True
你正在运行 Jupyter Notebook。
请注意,如果您正在运行 Colab 笔记本,那么这也是正确的。
在 MacOS 中
import psutil
def runninginJupyterNotebook():
for i in psutil.Process().parent().cmdline():
if "jupyter-notebook" in i:
return True
else:
return False
或者您可以在一行中设置一个变量:
RUNNING_IN_JUPYTER = any([i.endswith("bin/jupyter-notebook") for i in psutil.Process().parent().cmdline()])
与其他解决方案的比较:
get_ipython().__class__.__name__
get_ipython()
仅当您不关心它是否在 QtConsole 上运行时,所有解决方案才有效。
扫码咨询,免费领取项目管理大礼包!