Подтвердить что ты не робот

Как проверить, выполняется ли код в записной книжке IPython?

У меня есть пример кода на Python, который я хотел бы поделиться, который должен делать что-то другое, если он выполняется в терминале Python/IPython или в ноутбуке IPython.

Как я могу проверить свой код на Python, если он работает в ноутбуке IPython?

4b9b3361

Ответ 1

Вопрос в том, что вы хотите выполнить по-другому.

Мы делаем все возможное в IPython, чтобы ядро ​​не узнало, к какому интерфейсу подключено, и на самом деле вы даже можете подключить ядро ​​к множеству разных интерфейсов одновременно. Даже если вы можете заглянуть в тип stderr/out, чтобы знать, что вы в ядре ZMQ, или нет, это не гарантирует вам то, что у вас есть на другой стороне. Вы даже не можете иметь никаких интерфейсов.

Вероятно, вы должны написать свой код независимым образом, но если вы хотите отображать разные вещи, вы можете использовать богатую систему отображения (ссылка закреплена до версии 4.x IPython), чтобы отображать разные вещи в зависимости от интерфейса, но внешний интерфейс будет выбирать, а не библиотеку.

Ответ 2

Чтобы проверить, находитесь ли вы в ноутбуке, что может быть важно, например, при определении того, какого типа прогресс использовать, это сработало для меня:

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

Следующее работало для моих нужд:

get_ipython().__class__.__name__

Он возвращает 'TerminalInteractiveShell' на терминале IPython, 'ZMQInteractiveShell' на Jupyter (блокнот и qtconsole) и терпит неудачу (NameError) на регулярном интерпретаторе Python. Метод get_python(), по-видимому, доступен в глобальном пространстве имен по умолчанию при запуске IPython.

Обертка в простой функции:

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

Выше было протестировано с помощью Python 3.5.2, IPython 5.1.0 и Jupyter 4.2.1 на macOS 10.12 и Ubuntu 14.04.4 LTS

Ответ 4

Вы можете проверить, находится ли python в интерактивном режиме, с помощью следующего фрагмента [1]:

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
    return True

Ответ 5

Недавно я столкнулся с ошибкой в ноутбуке Jupyter, которая требует обходного пути, и я хотел сделать это без потери функциональности в других оболочках. Я понял, что решение 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']

Ответ 6

Ниже приведены случаи fooobar.com/questions/164999/... без необходимости разбора вывода 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

Ответ 7

Насколько я знаю, здесь есть 3 вида ipython, которые использовали ipykernel

  1. ipython qtconsole (для краткости "qtipython")
  2. IPython in spyder (для краткости "spyder")
  3. IPython в блокноте Jupyter (для краткости "jn")

использование 'spyder' in sys.modules может отличить spyder

но для qtipython и jn трудно различить причину

они имеют одинаковые sys.modules и тот же sys.modules IPython: get_ipython().config

Я нахожу разное между qtipython и jn:

при первом запуске os.getpid() в оболочке IPython получить номер pid

затем запустите ps -ef|grep [pid number]

мой pti qtipython 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 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 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 - это имя json в ipython, имя 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)

исходный код находится здесь: Detection Python Environment, особенно отличительный Spyder, блокнот Jupyter, Qtconsole.py

Ответ 8

Я бы порекомендовал избегать определения конкретного интерфейса, потому что их слишком много. Вместо этого вы можете просто проверить, работаете ли вы из среды 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, Google Colab и т.д., Он возвращает True.

Ответ 9

Я использую Django Shell Plus для запуска IPython, и я хотел сделать "запуск в ноутбуке" доступным как значение настроек Django. get_ipython() недоступен при загрузке настроек, поэтому я использую это (что не является пуленепробиваемым, но достаточно хорошим для локальных сред разработки, в которых оно использовалось):

import sys

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

Ответ 10

Один способ, который лаконичен и хорошо работает с линтерами (то есть никаких жалоб на неопределенные переменные),

def in_ipython():
    return hasattr(globals()["__builtins__"], "__IPYTHON__")
from timeit import timeit
timeit(in_ipython, number=100000)
> 0.026131024002097547

Примерно в два раза быстрее, но немного более многословно и может __IPYTHON__ предупреждение о __IPYTHON__ для __IPYTHON__:

def in_ipython():
    try:
        return __IPYTHON__
    except NameError:
        return False
timeit(in_ipython, number=100000)
> 0.013109331019222736

Ответ 11

Проверено на Python 3.7.3

Реализации CPython имеют имя __builtins__, доступное как часть их глобальных переменных, которые, между прочим. можно получить с помощью функции globals().
Если сценарий выполняется в среде Ipython, то __IPYTHON__ должен быть атрибутом __builtins__.
Поэтому приведенный ниже код возвращает True, если он работает под Ipython, или же он дает False

hasattr(__builtins__,'__IPYTHON__')