我有一些我想分享的 Python 代码示例,如果在终端 Python / IPython 或 IPython 笔记本中执行,它应该会做一些不同的事情。
我如何检查我的 Python 代码是否在 IPython 笔记本中运行?
我有一些我想分享的 Python 代码示例,如果在终端 Python / IPython 或 IPython 笔记本中执行,它应该会做一些不同的事情。
我如何检查我的 Python 代码是否在 IPython 笔记本中运行?
以下内容满足我的需求:
get_ipython().__class__.__name__
它'TerminalInteractiveShell'
在终端 IPython、'ZMQInteractiveShell'
Jupyter(笔记本和 qtconsole)上返回,并NameError
在常规 Python 解释器上失败()。启动 IPython 时,默认情况下该方法get_python()
似乎在全局命名空间中可用。
将其包装在一个简单的函数中:
def isnotebook():
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 进行了测试
要检查您是否在笔记本中,这可能很重要,例如在确定要使用哪种进度条时,这对我有用:
def in_ipynb():
try:
cfg = get_ipython().config
if cfg['IPKernelApp']['parent_appname'] == 'ipython-notebook':
return True
else:
return False
except NameError:
return False
您可以使用以下代码段[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
最近我在 Jupyter notebook中遇到了一个需要解决方法的错误,我想在不丢失其他 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']
已针对 python 3.7.3 测试
CPython 实现的名称__builtins__
可作为其全局变量的一部分,顺便说一句。可以通过函数 globals() 检索。
如果脚本在 Ipython 环境中运行,那么__IPYTHON__
应该是__builtins__
.
因此,如果在 Ipython 下运行,下面的代码将返回True
,否则返回False
hasattr(__builtins__,'__IPYTHON__')
问题是你想以不同的方式执行什么。
我们在 IPython 中尽最大努力防止内核知道连接到哪种前端,实际上您甚至可以让一个内核同时连接到许多不同的前端。即使您可以查看类型stderr/out
以了解您是否在 ZMQ 内核中,但它并不能保证您在另一端拥有什么。你甚至可以根本没有前端。
您可能应该以独立于前端的方式编写代码,但是如果您想显示不同的东西,您可以使用丰富的显示系统(链接固定到 IPython 的 4.x 版)根据前端显示不同的东西,但是前端会选择,而不是库。
您所要做的就是将这两个单元格放在笔记本的开头:
单元格 1:(标记为“代码”):
is_notebook = True
单元格 2:(标记为“原始 NBConvert”):
is_notebook = False
第一个单元格将始终执行,但第二个单元格仅在您将笔记本导出为 Python 脚本时才会执行。
稍后,您可以检查:
if is_notebook:
notebook_code()
else:
script_code()
希望这可以帮助。
据我所知,这里有 3 种使用的 ipythonipykernel
ipython qtconsole
(简称“qtipython”)使用'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('\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)
以下捕获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
我建议避免检测特定的前端,因为它们太多了。相反,您可以测试您是否在 iPython 环境中运行:
def is_running_from_ipython():
from IPython import get_ipython
return get_ipython() is not None
False
如果您running_from_ipython
从通常的 python 命令行调用,上面将返回。当您从 Jupyter Notebook、JupyterHub、iPython shell、Google Colab 等调用它时,它将返回True
.
一个非常简单高效的解决方案是检查调用堆栈的顶部是否引用了 IPython 环境,如下:
import traceback
def is_in_notebook():
rstk = traceback.extract_stack(limit=1)[0]
return rstk[0].startswith("<ipython")
此代码适用于 IPython 或 Jupyter 上的 Python 2 和 3,无需检查、设置或更改环境。
我正在使用 Django Shell Plus 来启动 IPython,并且我想让“在笔记本中运行”作为 Django 设置值可用。get_ipython()
加载设置时不可用,所以我使用它(这不是防弹的,但对于它所使用的本地开发环境来说已经足够好了):
import sys
if '--notebook' in sys.argv:
ENVIRONMENT = "notebook"
else:
ENVIRONMENT = "dev"
假设您可以控制 Jupyter Notebook,您可以:
在将其用作代码中的标志的单元格中设置环境值。在该单元格(或您要排除的所有单元格)中放置唯一注释
# exclude_from_export
%set_env is_jupyter=1
将笔记本导出为 python 脚本以在不同的上下文中使用。导出将排除注释的单元格,然后排除设置环境值的代码。注意:将your_notebook.ipynb替换为您的实际笔记本文件的名称。
jupyter nbconvert --to 脚本 --RegexRemovePreprocessor.patterns="['^# exclude_from_export']" your_notebook.ipynb
这将生成一个没有设置 jupyter 环境标志的文件,允许使用它的代码确定性地执行。
像这样的东西怎么样:
import sys
inJupyter = sys.argv[-1].endswith('json')
print(inJupyter);