Eu tenho algum exemplo de código Python que gostaria de compartilhar que deve fazer algo diferente se executado no terminal Python / IPython ou no notebook IPython.
Como posso verificar no meu código Python se ele está sendo executado no notebook IPython?
python
ipython
ipython-notebook
Christoph
fonte
fonte
Respostas:
A questão é o que você deseja executar de forma diferente.
Fazemos nosso melhor em IPython para evitar que o kernel saiba a que tipo de frontend está conectado e, na verdade, você pode até ter um kernel conectado a muitos front-ends diferentes ao mesmo tempo. Mesmo que você possa dar uma olhada no tipo de
stderr/out
para saber se você está em um kernel ZMQ ou não, isso não garante o que você tem do outro lado. Você poderia até mesmo não ter front-ends.Você provavelmente deve escrever seu código de uma maneira independente de front-end, mas se quiser exibir coisas diferentes, você pode usar o sistema de exibição rico (link fixado na versão 4.x do IPython) para exibir coisas diferentes dependendo do frontend, mas o frontend irá escolher, não a biblioteca.
fonte
\x1b[A
(mover para cima), portanto, não é possível imprimir barras aninhadas . Nenhum problema com ipywidgets , podemos usar widgets nativos do Jupyter para exibir barras de progresso. Mas então temos dois meios diferentes de exibir uma barra de progresso, e um aplicativo pode querer saber qual é o ambiente de exibição para adaptar e imprimir a barra compatível.%matplotlib inline
quando funcionar como um notebook, mas não em um terminal, já que isso não é necessário.O seguinte funcionou para minhas necessidades:
Ele retorna
'TerminalInteractiveShell'
em um terminal IPython,'ZMQInteractiveShell'
em Jupyter (notebook AND qtconsole) e fail (NameError
) em um interpretador Python regular. O métodoget_python()
parece estar disponível no namespace global por padrão quando o IPython é iniciado.Envolvendo-o em uma função simples:
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
O acima foi testado com Python 3.5.2, IPython 5.1.0 e Jupyter 4.2.1 no macOS 10.12 e Ubuntu 14.04.4 LTS
fonte
jupyter console
, infelizmenteget_ipython()
retorna uma instância deZMQInteractiveShell
tambémget_ipython().__class__.__module__ == "google.colab._shell"
test.py
depois executarfrom test import isnotebook; print(isnotebook())
em um Jupyter Notebook, ela será impressaTrue
. (Testado nas versões 5.2.1 e 6.0.1 do servidor Notebook.)Para verificar se você está em um notebook, o que pode ser importante, por exemplo, ao determinar que tipo de barra de progresso usar, isso funcionou para mim:
def in_ipynb(): try: cfg = get_ipython().config if cfg['IPKernelApp']['parent_appname'] == 'ipython-notebook': return True else: return False except NameError: return False
fonte
cfg['IPKernelApp']['parent_appname']
é umIPython.config.loader.LazyConfigValue
, que não se compara aoTrue
com"iypthon-notebook"
IPython.kernel.zmq.zmqshell.ZMQInteractiveShell
instância em ipynb (Jupyter) e umIPython.terminal.interactiveshell.TerminalInteractiveShell
REPL em um terminal, caso você precise diferenciar entre notebooks e terminal / consoles (o que afeta a plotagem).try
bloco por:return str(type(get_ipython())) == "<class 'ipykernel.zmqshell.ZMQInteractiveShell'>"
shell='PyDevTerminalInteractiveShell'
ao inspecionar o nome da classe.Você pode verificar se o python está no modo interativo com o seguinte snippet [1] :
def is_interactive(): import __main__ as main return not hasattr(main, '__file__')
Achei esse método muito útil porque faço muitos protótipos no notebook. Para fins de teste, uso parâmetros padrão. Caso contrário, eu li os parâmetros de
sys.argv
.from sys import argv if is_interactive(): params = [<list of default parameters>] else: params = argv[1:]
Após a implementação de
autonotebook
, você pode dizer se está em um notebook usando o código a seguir.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
fonte
is_interactive()
não faz distinção entre notebook e console.%run
do ipython não é interativa. Você poderia argumentar que deveria ser, mas ainda é uma pegadinha.is_interactive
) me parece basicamente irrelevante para a pergunta. É também de exatidão duvidosa; como @marscher aponta, ele conta qualquer coisa executada usandopython -c
como estando no modo "interativo", mesmo que isso não seja verdade. Não quero fazer isso sozinho, pois não é minha resposta, mas acho que seria melhorado simplesmente excluindo toda a primeira metade da resposta.Recentemente, encontrei um bug no notebook Jupyter que precisa de uma solução alternativa e eu queria fazer isso sem perder a funcionalidade em outros shells. Percebi que a solução do keflavich não funciona neste caso, pois
get_ipython()
está disponível apenas diretamente do notebook, e não de módulos importados. Então, descobri uma maneira de detectar no meu módulo se ele é importado e usado de um notebook Jupyter ou não: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
Os comentários são apreciados se for robusto o suficiente.
De forma semelhante, é possível obter algumas informações sobre o cliente e também a versão do 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']
fonte
'Ipython' in sys.modules
avaliaFalse
. Talvez você queira dizer'IPython' in sys.modules
? Isso estáTrue
no meu ambiente Jupyter. Osys.modules
dicionário também não inclui a'ipykernel'
chave - quando executado dentro de um notebook.Testado para python 3.7.3
As implementações de CPython têm o nome
__builtins__
disponível como parte de seus globais que btw. pode ser recuperado pela função globals ().Se um script estiver sendo executado em um ambiente Ipython,
__IPYTHON__
deve ser um atributo de__builtins__
.O código abaixo, portanto, retorna
True
se executado em Ipython ou então ele forneceFalse
hasattr(__builtins__,'__IPYTHON__')
fonte
O seguinte captura os casos de https://stackoverflow.com/a/50234148/1491619 sem a necessidade de analisar a saída 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
fonte
jupyter
se é umjupyter console
,jupyter qtconsole
oujupyter notebook
.Eu recomendaria evitar detectar front-end específico porque há muitos deles . Em vez disso, você pode apenas testar se está executando de dentro do ambiente iPython:
def is_running_from_ipython(): from IPython import get_ipython return get_ipython() is not None
Acima irá retornar
False
se você estiver invocando arunning_from_ipython
partir da linha de comando usual do python. Quando você o invoca do Jupyter Notebook, JupyterHub, shell do iPython, Google Colab, etc., ele retornaTrue
.fonte
get_ipython()
retorna<ipykernel.zmqshell.ZMQInteractiveShell at 0x7f750ba94320>
.get_ipython() is not None
retornarTrue
.Tudo que você precisa fazer é colocar essas duas células no início do seu caderno:
Célula 1: (marcada como "código"):
is_notebook = True
Célula 2: (marcada como "Raw NBConvert"):
is_notebook = False
A primeira célula sempre será executada, mas a segunda célula só será executada quando você exportar o bloco de notas como um script Python.
Mais tarde, você pode verificar:
if is_notebook: notebook_code() else: script_code()
Espero que isto ajude.
fonte
Que tal algo como isso:
import sys inJupyter = sys.argv[-1].endswith('json') print(inJupyter);
fonte
Até onde eu sei, aqui tem 3 tipos de ipython que usavam
ipykernel
ipython qtconsole
("qtipython" para breve)usar
'spyder' in sys.modules
pode distinguir spydermas para qtipython e jn são difíceis de distinguir causa
eles têm a mesma
sys.modules
configuração IPython:get_ipython().config
Acho uma diferença entre qtipython e jn:
Primeira corrida
os.getpid()
no shell IPython, obtenha o número pidentão corra
ps -ef|grep [pid number]
meu qtipython pid é 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
meu 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
o diferente de qtipython e jn é o nome json do ipython, os nomes json de jn são mais longos que os de qtipython
portanto, podemos detectar automaticamente todo o ambiente Python seguindo o 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)
o código-fonte está aqui: Detecção de ambiente Python, especialmente distinguir Spyder, Jupyter notebook, Qtconsole.py
fonte
Estou usando o Django Shell Plus para iniciar o IPython e queria disponibilizar 'running in notebook' como um valor de configurações do Django.
get_ipython()
não está disponível ao carregar as configurações, então eu uso isso (que não é à prova de balas, mas bom o suficiente para os ambientes de desenvolvimento local em que é usado):import sys if '--notebook' in sys.argv: ENVIRONMENT = "notebook" else: ENVIRONMENT = "dev"
fonte
Supondo que você tenha o controle do Jupyter Notebook, você pode:
defina um valor de ambiente em uma célula que usa isso como um sinalizador em seu código . Coloque um comentário exclusivo nessa célula (ou em todas as células que deseja excluir)
# exclude_from_export
% set_env is_jupyter = 1
Exporte o bloco de notas como um script Python para ser usado em um contexto diferente. A exportação excluiria a (s) célula (s) comentada (s) e, subsequentemente, o código que define o valor do ambiente. Nota: substitua your_notebook.ipynb pelo nome do seu arquivo de notebook real.
jupyter nbconvert --to script --RegexRemovePreprocessor.patterns = "['^ # exclude_from_export']" your_notebook.ipynb
Isso irá gerar um arquivo que não terá o sinalizador de ambiente jupyter definido, permitindo que o código que o usa seja executado de forma determinística.
fonte