Ich habe ein paar Python-Codebeispiele, die ich mitteilen möchte, die etwas anderes machen sollten, wenn sie im Terminal Python/IPython oder im IPython-Notebook ausgeführt werden.
Wie kann ich anhand meines Python-Codes überprüfen, ob er im IPython-Notebook ausgeführt wird?
Die Frage ist, was wollen Sie anders ausführen.
Wir tun unser Bestes in IPython, um zu verhindern, dass der Kernel weiß, an welche Art von Frontend angeschlossen ist, und tatsächlich können Sie sogar einen Kernel gleichzeitig mit vielen verschiedenen Frontends verbunden haben. Selbst wenn Sie einen Blick auf die Art von stderr/out
werfen können, um zu wissen, ob Sie sich in einem ZMQ-Kernel befinden oder nicht, garantiert er Ihnen nicht, was Sie auf der anderen Seite haben. Sie könnten sogar gar keine Frontends haben.
Sie sollten Ihren Code wahrscheinlich in einer vom Frontend unabhängigen Art und Weise schreiben, aber wenn Sie verschiedene Dinge anzeigen möchten, können Sie das rich-Anzeigesystem verwenden (Verknüpfung mit Version 4.x von IPython) , um je nach dem verschiedene Dinge anzuzeigen Frontend, aber das Frontend wählt, nicht die Bibliothek.
Um zu überprüfen, ob Sie sich in einem Notizbuch befinden, kann dies wichtig sein, z. Bei der Festlegung, welche Art von Fortschrittsbalken verwendet werden soll, hat dies für mich funktioniert
def in_ipynb():
try:
cfg = get_ipython().config
if cfg['IPKernelApp']['parent_appname'] == 'ipython-notebook':
return True
else:
return False
except NameError:
return False
Folgendes arbeitete für meine Bedürfnisse:
get_ipython().__class__.__name__
Es gibt 'TerminalInteractiveShell'
für ein Terminal-IPython, 'ZMQInteractiveShell'
für Jupyter (Notizbuch UND qtconsole) und schlägt fehl (NameError
) für einen normalen Python-Interpreter. Die Methode get_python()
scheint beim Start von IPython standardmäßig im globalen Namespace verfügbar zu sein.
Umhüllen mit einer einfachen Funktion:
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
Das obige wurde mit Python 3.5.2, IPython 5.1.0 und Jupyter 4.2.1 auf macOS 10.12 und Ubuntu 14.04.4 LTS getestet
Sie können mit dem folgenden Snippet [1] prüfen, ob sich Python im interactive -Modus befindet:
def is_interactive():
import __main__ as main
return not hasattr(main, '__file__')
Ich habe diese Methode sehr nützlich gefunden, weil ich viel Prototyping im Notebook durchführe. Zu Testzwecken verwende ich Standardparameter. Ansonsten lese ich die Parameter von sys.argv
.
from sys import argv
if is_interactive():
params = [<list of default parameters>]
else:
params = argv[1:]
Vor kurzem bin ich auf einen Fehler in Jupyter Notebook gestoßen, der eine Problemumgehung erfordert, und ich wollte dies tun, ohne die Funktionalität in anderen Shells zu verlieren. Mir wurde klar, dass keflavichs Lösung in diesem Fall nicht funktioniert, da get_ipython()
nur direkt vom Notebook aus verfügbar ist und nicht von importierten Modulen. So fand ich einen Weg, um von meinem Modul aus zu erkennen, ob es von einem Jupyter-Notebook importiert und verwendet wird oder nicht:
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
Kommentare sind erwünscht, wenn dies robust genug ist.
Auf ähnliche Weise ist es möglich, Informationen über den Client und die IPython-Version zu erhalten:
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']
Soweit ich weiß, hat Here 3 Arten von Ipython, die ipykernel
verwendet haben.
ipython qtconsole
(kurz "qtipython")verwenden Sie 'spyder' in sys.modules
kann Spyder unterscheiden
aber für qtipython und jn ist die Ursache schwer zu unterscheiden
sie haben die gleiche sys.modules
und dieselbe IPython-Konfiguration: get_ipython().config
Ich finde einen Unterschied zwischen qtipython und jn:
führen Sie zunächst os.getpid()
in der IPython-Shell aus, um die PID-Nummer zu erhalten
dann ps -ef|grep [pid number]
ausführen
mein qtipython pid ist 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
mein jn pid ist 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
der Unterschied zwischen qtipython und jn ist der Json-Name des Ipythons, der Json-Name von Jn ist länger als der von Qtipython
so können wir alle Python-Umgebungen durch folgenden Code automatisch erkennen:
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)
der Quellcode ist hier: Erkennung Python-Umgebung, besonders unterscheiden sich Spyder, Jupyter Notebook, Qtconsole.py
Im Folgenden werden die Fälle von https://stackoverflow.com/a/50234148/1491619 erfasst, ohne dass die Ausgabe von ps
analysiert werden muss.
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
Ich würde empfehlen, das Erkennen eines bestimmten Frontends zu vermeiden, da es zu viele gibt. Stattdessen können Sie einfach testen, ob Sie in einer iPython-Umgebung ausgeführt werden:
def is_running_from_ipython():
from IPython import get_ipython
return get_ipython() is None
Oben wird True zurückgegeben, wenn Sie running_from_ipython
über die normale Python-Befehlszeile aufrufen. Wenn Sie es über Jupyter Notebook, JupyterHub, iPython Shell, Google Colab usw. aufrufen, wird True zurückgegeben.
Ich benutze Django Shell Plus, um IPython zu starten, und ich wollte "Laufen im Notebook" als Django-Einstellungswert verfügbar machen. get_ipython()
steht beim Laden von Einstellungen nicht zur Verfügung. Daher verwende ich Folgendes (das ist nicht kugelsicher, aber gut genug für die lokalen Entwicklungsumgebungen, in denen es verwendet wird):
import sys
if '--notebook' in sys.argv:
ENVIRONMENT = "notebook"
else:
ENVIRONMENT = "dev"