Tengo un ejemplo de código de 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 de IPython.
¿Cómo puedo verificar en mi código Python si se está ejecutando en el cuaderno IPython?
python
ipython
ipython-notebook
Christoph
fuente
fuente
Respuestas:
La pregunta es qué desea ejecutar de manera diferente.
Hacemos nuestro mejor esfuerzo en IPython para evitar que el kernel sepa a qué tipo de frontend está conectado, y de hecho, incluso puede tener un kernel conectado a muchas 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ía no tener ninguna interfaz.Probablemente debería escribir su código de una manera independiente de la interfaz, pero si desea mostrar diferentes cosas, puede usar el sistema de visualización enriquecido (enlace anclado a la versión 4.x de IPython) para mostrar diferentes cosas dependiendo de la interfaz, pero el la interfaz elegirá, no la biblioteca.
fuente
\x1b[A
(subir), por lo que no es posible imprimir barras anidadas . No hay problema con ipywidgets , podemos usar widgets nativos de Jupyter para mostrar barras de progreso. Pero luego tenemos dos formas diferentes de mostrar una barra de progreso, y una aplicación puede querer saber cuál es el entorno de visualización para adaptar e imprimir la barra compatible.%matplotlib inline
cuando actúa como un cuaderno, pero no en una terminal, ya que no es necesario.Lo siguiente funcionó para mis necesidades:
Vuelve
'TerminalInteractiveShell'
en un terminal IPython,'ZMQInteractiveShell'
en Jupyter (notebook Y qtconsole) y falla (NameError
) en un intérprete de Python normal. El métodoget_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
fuente
jupyter console
, lamentablementeget_ipython()
devuelve una instancia deZMQInteractiveShell
tambiénget_ipython().__class__.__module__ == "google.colab._shell"
test.py
luego ejecutofrom test import isnotebook; print(isnotebook())
en un Jupyter Notebook, se imprimeTrue
. (Probado en las versiones 5.2.1 y 6.0.1 del servidor Notebook.)Para verificar si está en un cuaderno, lo que 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
fuente
cfg['IPKernelApp']['parent_appname']
es unIPython.config.loader.LazyConfigValue
, que no se comparaTrue
con"iypthon-notebook"
IPython.kernel.zmq.zmqshell.ZMQInteractiveShell
instancia en ipynb (Jupyter) y unIPython.terminal.interactiveshell.TerminalInteractiveShell
REPL en una terminal, en caso de que necesite diferenciar entre computadoras portátiles y terminales / consolas (lo que afecta el trazado).try
bloque con:return str(type(get_ipython())) == "<class 'ipykernel.zmqshell.ZMQInteractiveShell'>"
shell='PyDevTerminalInteractiveShell'
al inspeccionar el nombre de la clase.Puede verificar si Python está en modo interactivo con el siguiente fragmento [1] :
def is_interactive(): import __main__ as main return not hasattr(main, '__file__')
Este método me ha resultado muy útil porque hago muchos prototipos en el portátil. Para propósitos de prueba, utilizo parámetros predeterminados. 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:]
Después de la implementación de
autonotebook
, puede saber si está en un cuaderno usando el siguiente código.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
fuente
is_interactive()
no distingue entre portátil y consola.%run
ipython no es interactivo. Se podría argumentar que debería serlo, pero sigue siendo un problema.is_interactive
) me parece básicamente irrelevante para la pregunta. También es de dudosa exactitud; como señala @marscher, cuenta todo lo que se ejecuta usandopython -c
como si estuviera en modo "interactivo" aunque esto no sea cierto. No quiero hacerlo yo mismo ya que no es mi respuesta, pero creo que esto se mejoraría simplemente eliminando toda la primera mitad de la respuesta.Recientemente encontré un error en el cuaderno Jupyter que necesita una solución, y quería hacerlo sin perder funcionalidad en otros shells. Me di cuenta de que la solución de keflavich no funciona en este caso, porque
get_ipython()
solo está disponible directamente desde el portátil y no desde módulos importados. Entonces encontré una manera de detectar desde mi módulo si es importado y usado desde un cuaderno 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
Se agradecen los comentarios si esto es lo suficientemente sólido.
De manera similar, es posible obtener información sobre el cliente y también sobre la versión de 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']
fuente
'Ipython' in sys.modules
evalúa comoFalse
. ¿Quizás te refieres'IPython' in sys.modules
? Esto esTrue
en mi entorno de Jupyter. Elsys.modules
diccionario tampoco incluye la'ipykernel'
clave, cuando se ejecuta dentro de una computadora portátil.Probado para Python 3.7.3
Las implementaciones de CPython tienen el nombre
__builtins__
disponible como parte de sus globales que por cierto. se puede recuperar mediante la función globals ().Si un script se está ejecutando en un entorno Ipython, entonces
__IPYTHON__
debería ser un atributo de__builtins__
.Por lo tanto, el código a continuación devuelve
True
si se ejecuta bajo Ipython o de lo contrario daFalse
hasattr(__builtins__,'__IPYTHON__')
fuente
A continuación, se capturan los casos de https://stackoverflow.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://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
fuente
jupyter
si se trata de unajupyter console
,jupyter qtconsole
ojupyter notebook
.Recomendaría evitar detectar frontend específicos porque hay demasiados . En su lugar, puede probar si está ejecutando desde el entorno de iPython:
def is_running_from_ipython(): from IPython import get_ipython return get_ipython() is not None
Volverá arriba
False
si está invocandorunning_from_ipython
desde la línea de comando habitual de Python. Cuando lo invoca desde Jupyter Notebook, JupyterHub, iPython shell, Google Colab, etc., volveráTrue
.fuente
get_ipython()
regresa<ipykernel.zmqshell.ZMQInteractiveShell at 0x7f750ba94320>
.get_ipython() is not None
regresarTrue
.Todo lo que tiene que hacer es colocar estas dos celdas al principio de su cuaderno:
Celda 1: (marcada como "código"):
is_notebook = True
Celda 2: (marcada como "Raw NBConvert"):
is_notebook = False
La primera celda siempre se ejecutará, pero la segunda celda solo se ejecutará cuando exporte el cuaderno como una secuencia de comandos de Python.
Más tarde, puede comprobar:
if is_notebook: notebook_code() else: script_code()
Espero que esto ayude.
fuente
Qué tal algo como esto:
import sys inJupyter = sys.argv[-1].endswith('json') print(inJupyter);
fuente
Hasta donde yo sé, aquí tiene 3 tipos de ipython que usaban
ipykernel
ipython qtconsole
("qtipython" para abreviar)utilizar
'spyder' in sys.modules
puede distinguir spyderpero para qtipython y jn son difíciles de distinguir porque
tienen la misma
sys.modules
configuración de IPython:get_ipython().config
Encuentro una diferencia entre qtipython y jn:
primer intento
os.getpid()
en el shell de IPython obtiene el número pidentonces corre
ps -ef|grep [pid number]
mi pid qtipython es 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
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
lo diferente de qtipython y jn es el nombre json de ipython, el nombre json de jn es más largo que el de qtipython
entonces, podemos detectar automáticamente todo el entorno Python siguiendo el 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 del entorno de Python, distinguir especialmente Spyder, cuaderno Jupyter, Qtconsole.py
fuente
Estoy usando Django Shell Plus para iniciar IPython, y quería que 'ejecutar en el cuaderno' estuviera disponible como un valor de configuración de Django.
get_ipython()
no está disponible al cargar la configuración, por lo que uso esto (que no es a prueba de balas, pero lo suficientemente bueno para los entornos de desarrollo local en los que se usa):import sys if '--notebook' in sys.argv: ENVIRONMENT = "notebook" else: ENVIRONMENT = "dev"
fuente
Suponiendo que tenga el control de Jupyter Notebook, podría:
establezca un valor de entorno en una celda que use esto como una bandera en su código . Coloque un comentario único en esa celda (o en todas las celdas que desee excluir)
# exclude_from_export
% set_env is_jupyter = 1
Exporte el cuaderno como un script de Python para usarlo en un contexto diferente. La exportación excluiría las celdas comentadas y, posteriormente, el código que establece el valor del entorno. Nota: reemplace your_notebook.ipynb con el nombre de su archivo de cuaderno real.
jupyter nbconvert --to script --RegexRemovePreprocessor.patterns = "['^ # exclude_from_export']" your_notebook.ipynb
Esto generará un archivo que no tendrá el indicador de entorno jupyter configurado, lo que permitirá que el código que lo usa se ejecute de manera determinista.
fuente