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

时间:2022-10-09 06:14:20

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笔记本中运行?

7 个解决方案

#1


9  

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.

我们在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版本)根据前端显示不同的内容,但是前端会选择,而不是图书馆。

#2


27  

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

#3


16  

You can check whether python is in interactive mode using 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:]

#4


15  

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.

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

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测试了上述内容

#5


8  

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:

最近我在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

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']

#6


0  

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"

#7


0  

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

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

  1. ipython qtconsole ("qtipython" for short)
  2. ipython qtconsole(简称“qtipython”)
  3. IPython in spyder ("spyder" for short)
  4. spyder中的IPython(简称“spyder”)
  5. IPython in jupyter notebook ("jn" for short)
  6. 在jupyter笔记本中的IPython(简称“jn”)

use 'spyder' in sys.modules can distinguish spyder

在sys.modules中使用'spyder'可以区分spyder

but for qtipython and jn are hard to distinguish cause

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

they have same sys.modules and same IPython config:get_ipython().config

他们有相同的sys.modules和相同的IPython配置:get_ipython()。config

I find a different between qtipython and jn:

我发现qtipython和jn之间有所不同:

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

首先在IPython shell中运行os.getpid()获取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笔记本,Qtconsole.py

#1


9  

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.

我们在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版本)根据前端显示不同的内容,但是前端会选择,而不是图书馆。

#2


27  

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

#3


16  

You can check whether python is in interactive mode using 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:]

#4


15  

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.

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

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测试了上述内容

#5


8  

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:

最近我在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

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']

#6


0  

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"

#7


0  

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

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

  1. ipython qtconsole ("qtipython" for short)
  2. ipython qtconsole(简称“qtipython”)
  3. IPython in spyder ("spyder" for short)
  4. spyder中的IPython(简称“spyder”)
  5. IPython in jupyter notebook ("jn" for short)
  6. 在jupyter笔记本中的IPython(简称“jn”)

use 'spyder' in sys.modules can distinguish spyder

在sys.modules中使用'spyder'可以区分spyder

but for qtipython and jn are hard to distinguish cause

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

they have same sys.modules and same IPython config:get_ipython().config

他们有相同的sys.modules和相同的IPython配置:get_ipython()。config

I find a different between qtipython and jn:

我发现qtipython和jn之间有所不同:

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

首先在IPython shell中运行os.getpid()获取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笔记本,Qtconsole.py