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

2025-03-13 09:06:00
admin
原创
88
摘要:问题描述:我有一些 Python 代码示例想要分享,如果在终端 Python / IPython 或 IPython 笔记本中执行,应该会做一些不同的事情。如何检查我的 Python 代码是否在 IPython 笔记本中运行?解决方案 1:以下满足了我的需求:get_ipython().__class__._...

问题描述:

我有一些 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

  1. ipython qtconsole(简称“qtipython”)

  2. spyder 中的 IPython(简称“spyder”)

  3. 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,你可以:

  1. 在单元格中设置环境值,并将其用作代码中的标志。在该单元格中放置一个唯一的注释(或要排除的所有单元格)

排除从导出

%set_env is_jupyter = 1

  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 上运行时,所有解决方案才有效。

来源:https://stackoverflow.com/a/65498256/2132157

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   4046  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2770  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   90  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   105  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   93  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用