nbviewer - ¿Cómo puedo verificar si el código se ejecuta en el cuaderno de IPython?
manual jupyter notebook (8)
Estoy usando Django Shell Plus para iniciar IPython, y quería hacer que ''ejecutar en el cuaderno'' esté disponible como un valor de configuración de Django. get_ipython()
no está disponible cuando se cargan los ajustes, así que uso esto (que no es a prueba de balas, pero es lo suficientemente bueno para los entornos de desarrollo locales en los que se usa):
import sys
if ''--notebook'' in sys.argv:
ENVIRONMENT = "notebook"
else:
ENVIRONMENT = "dev"
Tengo un ejemplo de código Python que me gustaría compartir y que debería hacer algo diferente si se ejecuta en el terminal Python / IPython o en el cuaderno IPython
¿Cómo puedo verificar desde mi código Python si se está ejecutando en la notebook IPython?
La pregunta es qué quieres ejecutar de manera diferente.
Hacemos todo lo posible para evitar que el kernel sepa a qué tipo de frontend está conectado, e incluso puede tener un kernel conectado a muchos frontends diferentes al mismo tiempo. Incluso si puede echar un vistazo al tipo de stderr/out
para saber si está en un kernel ZMQ o no, no le garantiza lo que tiene en el otro lado. Incluso podrías no tener frontends en absoluto.
Probablemente debería escribir su código de manera independiente en el frontend, pero si desea mostrar diferentes elementos, puede usar el sistema de visualización enriquecido (enlace fijado a la versión 4.x de IPython) para mostrar diferentes elementos según el frontend, pero Frontend elegirá, no la biblioteca.
Lo siguiente captura los casos de https://.com/a/50234148/1491619 sin necesidad de analizar la salida 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://.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
Lo siguiente funcionó para mis necesidades:
get_ipython().__class__.__name__
Devuelve ''TerminalInteractiveShell''
en un terminal IPython, ''ZMQInteractiveShell''
en Jupyter (notebook AND qtconsole) y falla ( NameError
) en un intérprete Python regular. El método get_python()
parece estar disponible en el espacio de nombres global de forma predeterminada cuando se inicia IPython.
Envolviéndolo en una función 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
Lo anterior se probó con Python 3.5.2, IPython 5.1.0 y Jupyter 4.2.1 en macOS 10.12 y Ubuntu 14.04.4 LTS
Para comprobar si estás en un cuaderno, lo cual puede ser importante, por ejemplo, al determinar qué tipo de barra de progreso usar, esto funcionó para mí:
def in_ipynb():
try:
cfg = get_ipython().config
if cfg[''IPKernelApp''][''parent_appname''] == ''ipython-notebook'':
return True
else:
return False
except NameError:
return False
Puede verificar si Python está en modo interactivo usando el siguiente fragmento de código [1] :
def is_interactive():
import __main__ as main
return not hasattr(main, ''__file__'')
He encontrado este método muy útil porque hago muchos prototipos en el cuaderno. Para propósitos de prueba, uso los parámetros por defecto. De lo contrario, leo los parámetros de sys.argv
.
from sys import argv
if is_interactive():
params = [<list of default parameters>]
else:
params = argv[1:]
Que yo sepa, aquí hay 3 tipos de ipython que usaban ipykernel
-
ipython qtconsole
("qtipython" para abreviar) - IPython en spyder ("spyder" para abreviar)
- IPython en el cuaderno jupyter ("jn" para abreviar)
usar ''spyder'' in sys.modules
puede distinguir spyder
pero para qtipython y jn son difíciles de distinguir porque
tienen los mismos sys.modules
y la misma configuración de IPython: get_ipython().config
Encuentro una diferencia entre qtipython y jn:
primero ejecute os.getpid()
en el shell de IPython para obtener el número pid
luego ejecute ps -ef|grep [pid number]
mi qtipython pid es 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
mi jn pid es 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
el diferente de qtipython y jn es el nombre json del ipython, el nombre json de jn es más largo que el qtipython
Por lo tanto, podemos detectar automáticamente todos los entornos Python mediante el siguiente código:
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)
El código fuente está aquí: Detección Python Environment, especialmente Spyder, portátil Jupyter, Qtconsole.py
Recientemente, encontré un error en la notebook Jupyter que necesita una solución, y quería hacer esto sin perder la funcionalidad en otros shells. Me di cuenta de que la solución de Keflavich no funciona en este caso, porque get_ipython()
está disponible solo directamente desde el portátil, y no desde módulos importados. Así que encontré una forma de detectar desde mi módulo si se importaba y se usaba desde una notebook Jupyter o no:
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
Los comentarios son apreciados si esto es lo suficientemente robusto.
De manera similar, es posible obtener información sobre el cliente y la versión de IPython también:
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'']