J'ai un exemple de code Python que j'aimerais partager 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 s'exécute dans le bloc-notes IPython?
python
ipython
ipython-notebook
Christoph
la source
la source
Réponses:
La question est de savoir ce que vous voulez exécuter différemment.
Nous faisons de notre mieux dans IPython pour empêcher le noyau de savoir à quel type de frontend est connecté, et en fait, vous pouvez même avoir un noyau connecté à plusieurs 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, cela ne vous garantit pas ce que vous avez de l'autre côté. Vous pourriez même ne pas avoir d'interface du tout.Vous devriez probablement écrire votre code de manière indépendante du frontend, mais si vous voulez afficher différentes choses, vous pouvez utiliser le système d'affichage riche (lien épinglé à la version 4.x d'IPython) pour afficher différentes choses en fonction du frontend, mais le frontend choisira, pas la bibliothèque.
la source
\x1b[A
(monter), il n'est donc pas possible d'imprimer des barres imbriquées . Pas de problème avec ipywidgets , nous pouvons utiliser des widgets Jupyter natifs pour afficher les barres de progression. Mais alors nous avons deux moyens différents d'afficher une barre de progression, et une application peut vouloir savoir quel est l'environnement d'affichage afin d'adapter et d'imprimer la barre compatible.%matplotlib inline
quand elle agit comme un ordinateur portable, mais pas dans un terminal, car cela n'est pas nécessaire.Ce qui suit a fonctionné pour mes besoins:
Il retourne
'TerminalInteractiveShell'
sur un terminal IPython,'ZMQInteractiveShell'
sur Jupyter (notebook ET qtconsole) et échoue (NameError
) sur un interpréteur Python classique. La méthodeget_python()
semble être disponible dans l'espace de noms global par défaut au démarrage d'IPython.Emballer 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
la source
jupyter console
,get_ipython()
renvoie malheureusement une instance deZMQInteractiveShell
aussiget_ipython().__class__.__module__ == "google.colab._shell"
test.py
puis que je l' exécutefrom test import isnotebook; print(isnotebook())
dans un bloc-notes Jupyter, elle s'imprimeTrue
. (Testé sur les versions 5.2.1 et 6.0.1 du serveur Notebook.)Pour vérifier si vous êtes dans un cahier, ce qui peut être important, par exemple pour déterminer le type de barre de progression à 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
la source
cfg['IPKernelApp']['parent_appname']
est unIPython.config.loader.LazyConfigValue
, qui ne se compare pas àTrue
avec"iypthon-notebook"
IPython.kernel.zmq.zmqshell.ZMQInteractiveShell
instance dans ipynb (Jupyter) et uneIPython.terminal.interactiveshell.TerminalInteractiveShell
dans un terminal REPL, au cas où vous auriez besoin de faire la différence entre les notebooks et les terminaux / consoles (ce qui affecte le traçage).try
bloc par:return str(type(get_ipython())) == "<class 'ipykernel.zmqshell.ZMQInteractiveShell'>"
shell='PyDevTerminalInteractiveShell'
lors de l'inspection du nom de la classe.Vous pouvez vérifier si python est en mode interactif avec l'extrait de code suivant [1] :
def is_interactive(): import __main__ as main return not hasattr(main, '__file__')
J'ai trouvé cette méthode très utile car je fais beaucoup de prototypage dans le cahier. À des fins de test, j'utilise les paramètres par défaut. Sinon, je lis les paramètres de
sys.argv
.from sys import argv if is_interactive(): params = [<list of default parameters>] else: params = argv[1:]
Après l'implémentation de
autonotebook
, vous pouvez savoir si vous êtes dans un bloc-notes à l'aide du code suivant.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
la source
is_interactive()
ne fait pas la distinction entre ordinateur portable et console.%run
depuis ipython n'est pas interactif. Vous pourriez dire que ça devrait l'être, mais c'est toujours un piège.is_interactive
) me semble être fondamentalement sans rapport avec la question. C'est aussi d'une exactitude douteuse; comme le fait remarquer @marscher, il compte tout ce qui est exécuté en utilisantpython -c
comme étant en mode "interactif" même si ce n'est pas vrai. Je ne veux pas le faire moi-même car ce n'est pas ma réponse, mais je pense que cela serait amélioré en supprimant simplement la première moitié de la réponse.Récemment, j'ai rencontré un bogue dans le notebook Jupyter qui nécessite une solution de contournement, et je voulais le faire sans perdre les fonctionnalités des autres shells. Je me suis rendu compte que la solution de keflavich ne fonctionnait pas dans ce cas, car elle
get_ipython()
n'est disponible que directement depuis le notebook, et non depuis des 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 notebook 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 si cela est suffisamment robuste.
De la même manière, il est possible d'obtenir des informations sur le client, ainsi que sur la version 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']
la source
'Ipython' in sys.modules
évalue àFalse
. Vous voulez dire peut-être'IPython' in sys.modules
? C'estTrue
dans mon environnement Jupyter. Lesys.modules
dictionnaire n'inclut pas non plus la'ipykernel'
clé - lors de l'exécution à l'intérieur d'un cahier.Testé pour python 3.7.3
Les implémentations CPython ont le nom
__builtins__
disponible dans le cadre de leurs globals qui btw. peut être récupéré par la fonction globals ().Si un script s'exécute dans un environnement Ipython, il
__IPYTHON__
doit être un attribut de__builtins__
.Le code ci-dessous retourne donc
True
s'il est exécuté sous Ipython ou bien il donneFalse
hasattr(__builtins__,'__IPYTHON__')
la source
Ce qui suit capture les cas de https://stackoverflow.com/a/50234148/1491619 sans avoir besoin d'analyser la sortie de
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
la source
jupyter
que ce soit unjupyter console
,jupyter qtconsole
oujupyter notebook
.Je recommanderais d'éviter de détecter un frontend spécifique car il y en a trop . Au lieu de cela, vous pouvez simplement tester si vous exécutez à partir de l'environnement iPython:
def is_running_from_ipython(): from IPython import get_ipython return get_ipython() is not None
Ci-dessus reviendra
False
si vous appelez àrunning_from_ipython
partir de la ligne de commande python habituelle. Lorsque vous l'invoquez à partir de Jupyter Notebook, JupyterHub, iPython shell, Google Colab, etc., il reviendraTrue
.la source
get_ipython()
revient<ipykernel.zmqshell.ZMQInteractiveShell at 0x7f750ba94320>
.get_ipython() is not None
retournerTrue
.Tout ce que vous avez à faire est de placer ces deux cellules au début de votre carnet:
Cellule 1: (marquée comme "code"):
is_notebook = True
Cellule 2: (marquée comme "Raw NBConvert"):
is_notebook = False
La première cellule sera toujours exécutée, mais la deuxième cellule ne sera exécutée que lorsque vous exporterez le notebook en tant que script Python.
Plus tard, vous pouvez vérifier:
if is_notebook: notebook_code() else: script_code()
J'espère que cela t'aides.
la source
Que diriez-vous quelque chose comme ça:
import sys inJupyter = sys.argv[-1].endswith('json') print(inJupyter);
la source
Autant que je sache, voici 3 types d'ipython qui utilisaient
ipykernel
ipython qtconsole
("qtipython" pour faire court)utilisation
'spyder' in sys.modules
peut distinguer spydermais pour qtipython et jn sont difficiles à distinguer cause
ils ont la même
sys.modules
et la même configuration IPython:get_ipython().config
Je trouve un différent entre qtipython et jn:
première exécution
os.getpid()
dans le shell IPython obtenir le numéro pidpuis courir
ps -ef|grep [pid number]
mon pid qtipython 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 jn pid 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
le différent de qtipython et jn est le nom json d'ipython, le nom json de jn est plus long que celui de qtipython
Ainsi, nous pouvons détecter automatiquement tout l'environnement Python en suivant le code:
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 de l'environnement Python, surtout distinguer Spyder, notebook Jupyter, Qtconsole.py
la source
J'utilise Django Shell Plus pour lancer IPython, et je voulais rendre `` l'exécution dans le notebook '' disponible en tant que valeur de paramètres Django.
get_ipython()
n'est pas disponible lors du chargement des paramètres, donc j'utilise ceci (qui n'est pas à l'épreuve des balles, mais assez bon pour les environnements de développement local dans lesquels il est utilisé):import sys if '--notebook' in sys.argv: ENVIRONMENT = "notebook" else: ENVIRONMENT = "dev"
la source
En supposant que vous contrôliez le bloc-notes Jupyter, vous pouvez:
définissez une valeur d'environnement dans une cellule qui l'utilise comme indicateur dans votre code . Placez un commentaire unique dans cette cellule (ou dans toutes les cellules que vous souhaitez exclure)
# exclude_from_export
% set_env is_jupyter = 1
Exportez le notebook sous forme de script python à utiliser dans un contexte différent. L'exportation exclurait la ou les cellules commentées et, par la suite, le code définissant la valeur d'environnement. Remarque: remplacez votre_notebook.ipynb par le nom de votre fichier de bloc-notes actuel.
jupyter nbconvert --to script --RegexRemovePreprocessor.patterns = "['^ # exclude_from_export']" votre_notebook.ipynb
Cela générera un fichier qui n'aura pas l'indicateur d'environnement jupyter défini, ce qui permettra au code qui l'utilise de s'exécuter de manière déterministe.
la source