如何检查代码是否在 IPython 笔记本中执行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15411967/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 20:03:35  来源:igfitidea点击:

How can I check if code is executed in the IPython notebook?

pythonipythonipython-notebook

提问by Christoph

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.

我有一些我想分享的 Python 代码示例,如果在终端 Python/IPython 或 IPython 笔记本中执行,它应该会做一些不同的事情。

How can I check from my Python code if it's running in the IPython notebook?

如何检查我的 Python 代码是否在 IPython 笔记本中运行?

采纳答案by Matt

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/outto 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.

我们在 IPython 中尽最大努力防止内核知道连接到哪种前端,实际上您甚至可以让内核同时连接到许多不同的前端。即使您可以通过查看类型stderr/out来了解您是否在 ZMQ 内核中,它也不能保证您在另一侧拥有什么。你甚至可以根本没有前端。

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.

您可能应该以独立于前端的方式编写代码,但是如果您想显示不同的内容,您可以使用丰富的显示系统(链接固定到 IPython 4.x 版)根据前端显示不同的内容,但是前端会选择,而不是图书馆。

回答by Till Hoffmann

You can check whether python is in interactivemode with the following snippet [1]:

您可以使用以下代码段[1]检查 python 是否处于交互模式:

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.

我发现这种方法非常有用,因为我在笔记本中做了很多原型设计。出于测试目的,我使用默认参数。否则,我从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.

按照 的实现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
    return True

回答by keflavich

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

回答by deeenes

Recently I encountered a bug in Jupyter notebookwhich needs a workaround, and I wanted to do this without loosing functionality in other shells. I realized that keflavich's solutiondoes 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:

最近我在 Jupyter notebook 中遇到了一个需要解决方法的错误,我想在不丢失其他 shell 中的功能的情况下做到这一点。我意识到keflavich 的解决方案在这种情况下不起作用,因为get_ipython()只能直接从笔记本中获得,而不能从导入的模块中获得。所以我找到了一种方法来检测我的模块是否从 Jupyter notebook 导入和使用:

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:

类似的方式可以获得有关客户端的一些信息,以及 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']

回答by Gustavo Bezerra

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 method get_python()seems to be available in the global namespace by default when IPython is started.

'TerminalInteractiveShell'在终端 IPython、'ZMQInteractiveShell'Jupyter(笔记本和 qtconsole)上返回,并NameError在常规 Python 解释器上失败 ( )。get_python()当 IPython 启动时,该方法似乎默认在全局命名空间中可用。

Wrapping it in a simple function:

将其包装在一个简单的函数中:

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

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

以上已在 macOS 10.12 和 Ubuntu 14.04.4 LTS 上使用 Python 3.5.2、IPython 5.1.0 和 Jupyter 4.2.1 进行测试

回答by user31415629

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):

我正在使用 Django Shell Plus 来启动 IPython,并且我想让“在笔记本中运行”作为 Django 设置值可用。get_ipython()加载设置时不可用,所以我使用它(这不是防弹的,但对于使用它的本地开发环境来说已经足够了):

import sys

if '--notebook' in sys.argv:
    ENVIRONMENT = "notebook"
else:
    ENVIRONMENT = "dev"

回答by Yang

As far as I know, Here has 3 kinds of ipython that used ipykernel

据我所知,这里有 3 种使用的 ipython ipykernel

  1. ipython qtconsole("qtipython" for short)
  2. IPython in spyder ("spyder" for short)
  3. IPython in jupyter notebook ("jn" for short)
  1. ipython qtconsole(简称“qtipython”)
  2. spyder 中的 IPython(简称“spyder”)
  3. jupyter notebook 中的 IPython(简称“jn”)

use 'spyder' in sys.modulescan distinguish spyder

使用'spyder' in sys.modules可以区分spyder

but for qtipython and jn are hard to distinguish cause

但是对于 qtipython 和 jn 很难区分原因

they have same sys.modulesand same IPython config:get_ipython().config

它们具有相同的sys.modulesIPython 配置:get_ipython().config

I find a different between qtipython and jn:

我发现 qtipython 和 jn 之间存在差异:

first run os.getpid()in IPython shell get the pid number

首先os.getpid()在 IPython shell 中运行获取 pid 号

then run ps -ef|grep [pid number]

然后运行 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

我的 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

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

我的 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

the different of qtipython and jn is the ipython's json name, jn's json name are longer than qtipython's

qtipython 和 jn 的不同是 ipython 的 json 名称,jn 的 json 名称比 qtipython 的要长

so, we can auto detection all Python Environment by following code:

因此,我们可以通过以下代码自动检测所有 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)

the source code are here:Detection Python Environment, Especially distinguish Spyder, Jupyter notebook, Qtconsole.py

源代码在这里:检测Python环境,特别区分Spyder、Jupyter notebook、Qtconsole.py

回答by Bob Weigel

The following captures the cases of https://stackoverflow.com/a/50234148/1491619without needing to parse the output of ps

下面捕获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

回答by Shital Shah

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:

我建议避免检测特定的前端,因为它们太多了。相反,您可以测试是否在 iPython 环境中运行:

def is_running_from_ipython():
    from IPython import get_ipython
    return get_ipython() is not None

Above will return Falseif you are invoking running_from_ipythonfrom usual python command line. When you invoke it from Jupyter Notebook, JupyterHub, iPython shell, Google Colab etc then it will return True.

False如果您running_from_ipython从通常的 python 命令行调用,上面将返回。当您从 Jupyter Notebook、JupyterHub、iPython shell、Google Colab 等调用它时,它将返回True.

回答by Robert Nowak

Tested for python 3.7.3

测试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 Trueif run under Ipython or else it gives False

CPython 实现的名称__builtins__可用作其全局变量的一部分,顺便说一句。可以通过函数 globals() 检索。
如果脚本在 Ipython 环境中运行,则__IPYTHON__应该是__builtins__.
因此,True如果在 Ipython 下运行,则下面的代码将返回,否则它会给出False

hasattr(__builtins__,'__IPYTHON__')