Comment puis-je vérifier si le code est exécuté dans le bloc-notes IPython?

j'ai un exemple de code Python que j'aimerais partager et qui devrait faire quelque chose de différent s'il est exécuté dans le terminal Python / IPython ou dans le notebook IPython.

Comment puis-je vérifier à partir de mon code Python s'il fonctionne dans le carnet IPython?

43
demandé sur Christoph 2013-03-14 18:25:44

7 réponses

la question Est de savoir ce que vous voulez exécuter différemment.

nous faisons de notre mieux dans IPython empêcher le noyau de savoir à quel type de frontend est connecté, et en fait vous pouvez même avoir un noyau connecté à de nombreux frontends différents en même temps. Même si vous pouvez jeter un oeil au type de stderr/out pour savoir si vous êtes dans un noyau ZMQ ou non, il ne vous garantit pas ce que vous avez de l'autre côté. Vous pourriez même pas des interfaces à tous.

vous devriez probablement écrire votre code de manière indépendante, mais si vous voulez afficher des choses différentes, vous pouvez utiliser le système d'affichage riche (lien épinglé à la version 4.x D'IPython) pour afficher des choses différentes selon le frontend, mais le frontend choisira, pas la bibliothèque.

9
répondu Matt 2016-02-26 19:12:54

pour vérifier si vous êtes dans un notebook, ce qui peut être important, par exemple lors de la détermination de ce type de progressbar à utiliser, cela a fonctionné pour moi:

def in_ipynb():
    try:
        cfg = get_ipython().config 
        if cfg['IPKernelApp']['parent_appname'] == 'ipython-notebook':
            return True
        else:
            return False
    except NameError:
        return False
29
répondu keflavich 2014-07-24 15:04:56

vous pouvez vérifier si python est en mode interactif en utilisant l'extrait suivant [1] :

def is_interactive():
    import __main__ as main
    return not hasattr(main, '__file__')

j'ai trouvé cette méthode très utile parce que je fais beaucoup de prototypage dans le cahier. Pour les tests, j'utilise les paramètres par défaut. Sinon, j'ai lu les paramètres de sys.argv .

from sys import argv

if is_interactive():
    params = [<list of default parameters>]
else:
    params = argv[1:]
16
répondu Till Hoffmann 2017-05-23 12:26:24

ce qui suit a fonctionné pour mes besoins:

get_ipython().__class__.__name__

Il retourne 'TerminalInteractiveShell' sur un terminal IPython, 'ZMQInteractiveShell' sur Jupyter (ordinateurs portables ET qtconsole) et échoue ( NameError ) sur une base régulière de l'interpréteur Python. La méthode get_python() semble être disponible dans L'espace de noms global par défaut quand IPython est lancé.

enveloppant dans une fonction simple:

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

ce qui précède a été testé avec Python 3.5.2, IPython 5.1.0 et Jupyter 4.2.1 sur macOS 10.12 et Ubuntu 14.04.4 LTS

16
répondu Gustavo Bezerra 2017-05-25 09:06:39

J'ai récemment rencontré un bug dans le carnet de notes de Jupyter qui a besoin d'être contourné, et je voulais le faire sans perdre de fonctionnalité dans d'autres coquilles. Je me suis rendu compte que solution de keflavich ne fonctionne pas dans ce cas, parce que get_ipython() est disponible seulement directement à partir du carnet, et non à partir de modules importés. J'ai donc trouvé un moyen de détecter à partir de mon module s'il est importé et utilisé à partir D'un carnet Jupyter ou non:

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

les commentaires sont appréciés s'ils sont suffisamment robustes.

de la même façon, il est possible d'obtenir des informations sur le client, et la version IPython ainsi:

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']
8
répondu deeenes 2017-05-23 12:03:02

J'utilise Django Shell Plus pour lancer IPython, et je voulais rendre "running in notebook" disponible comme valeur de réglage de Django. get_ipython() n'est pas disponible pour les paramètres de chargement, donc j'utilise ceci (qui n'est pas à l'épreuve des balles, mais assez bon pour les environnements de développement local dans lequel il est utilisé):

import sys

if '--notebook' in sys.argv:
    ENVIRONMENT = "notebook"
else:
    ENVIRONMENT = "dev"
0
répondu user31415629 2017-11-03 11:02:39

autant que je sache, voici 3 types d'ipython qui utilisé ipykernel

  1. ipython qtconsole ("qtipython "pour faire court
  2. IPython en spyder ("spyder" pour faire court)
  3. IPython dans jupyter pour ordinateur portable ("jn" pour faire court)

utiliser 'spyder' in sys.modules peut distinguer spyder

mais pour qtipython et jn sont difficiles à distinguer cause

ils ont le même sys.modules et la même config IPython: get_ipython().config

j'ai trouver un autre entre qtipython et jn:

première os.getpid() dans IPython shell obtenir le numéro de pid

puis exécuter ps -ef|grep [pid number]

mon qtipython pid est 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

mon pid jn est 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

la différence de qtipython et jn est le le nom JSON d'ipython, le nom json de jn sont plus longs que qtipython

ainsi, nous pouvons détecter automatiquement tout L'environnement Python par le code suivant:

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)

le code source est ici: détection environnement Python, en particulier distinguer Spyder, carnet Jupyter, Qtconsole.py

0
répondu Yang 2018-05-08 12:53:23