Ich möchte ein Python-Codebeispiel teilen, das etwas anderes tun sollte, wenn es im Terminal Python / IPython oder im IPython-Notizbuch ausgeführt wird.
Wie kann ich anhand meines Python-Codes überprüfen, ob er im IPython-Notizbuch ausgeführt wird?
python
ipython
ipython-notebook
Christoph
quelle
quelle
Antworten:
Die Frage ist, was Sie anders ausführen möchten.
Wir tun unser Bestes in IPython, um zu verhindern, dass der Kernel weiß, mit welcher Art von Frontend verbunden ist, und tatsächlich können Sie sogar einen Kernel gleichzeitig mit vielen verschiedenen Frontends verbinden. Selbst wenn Sie einen Blick auf die Art
stderr/out
werfen können, um zu wissen, ob Sie sich in einem ZMQ-Kernel befinden oder nicht, garantiert dies Ihnen nicht, was Sie auf der anderen Seite haben. Sie könnten sogar überhaupt keine Frontends haben.Sie sollten Ihren Code wahrscheinlich unabhängig vom Frontend schreiben. Wenn Sie jedoch verschiedene Dinge anzeigen möchten, können Sie das Rich-Display-System (Link an Version 4.x von IPython angeheftet) verwenden , um je nach Frontend verschiedene Dinge anzuzeigen Das Frontend wählt, nicht die Bibliothek.
quelle
\x1b[A
(nach oben), sodass verschachtelte Balken nicht gedruckt werden können . Kein Problem mit ipywidgets , wir können native Jupyter-Widgets verwenden, um Fortschrittsbalken anzuzeigen. Dann haben wir zwei verschiedene Möglichkeiten, einen Fortschrittsbalken anzuzeigen, und eine Anwendung möchte möglicherweise wissen, wie die Anzeigeumgebung aussieht, um den kompatiblen Balken anzupassen und zu drucken.%matplotlib inline
wenn sie als Notebook fungiert, jedoch nicht in einem Terminal, da dies nicht erforderlich ist.Folgendes hat für meine Bedürfnisse funktioniert:
Es kehrt
'TerminalInteractiveShell'
auf einem Terminal-IPython'ZMQInteractiveShell'
auf Jupyter (Notebook UND qtconsole) zurück und schlägtNameError
auf einem normalen Python-Interpreter fehl ( ). Die Methodeget_python()
scheint standardmäßig im globalen Namespace verfügbar zu sein, wenn IPython gestartet wird.Wickeln Sie es in eine einfache 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 unter macOS 10.12 und Ubuntu 14.04.4 LTS getestet
quelle
jupyter console
, leiderget_ipython()
gibt eine Instanz vonZMQInteractiveShell
auchget_ipython().__class__.__module__ == "google.colab._shell"
test.py
dannfrom test import isnotebook; print(isnotebook())
in einem Jupyter-Notizbuch ausführe , wird sie gedrucktTrue
. (Getestet auf Notebook-Server-Versionen 5.2.1 und 6.0.1.)Um zu überprüfen, ob Sie sich in einem Notizbuch befinden, was wichtig sein kann, z. B. wenn Sie bestimmen, 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
quelle
cfg['IPKernelApp']['parent_appname']
befindet sich einIPython.config.loader.LazyConfigValue
, der nichtTrue
mit"iypthon-notebook"
IPython.kernel.zmq.zmqshell.ZMQInteractiveShell
Instanz in ipynb (Jupyter) und eineIPython.terminal.interactiveshell.TerminalInteractiveShell
in einem Terminal REPL zurück, falls Sie zwischen Notebooks und Terminal / Konsolen unterscheiden müssen (was sich auf das Plotten auswirkt).try
Blocks ersetzen durch:return str(type(get_ipython())) == "<class 'ipykernel.zmqshell.ZMQInteractiveShell'>"
shell='PyDevTerminalInteractiveShell'
beim Überprüfen des Klassennamens angezeigt.Mit dem folgenden Snippet [1] können Sie überprüfen, ob sich Python im interaktiven Modus befindet :
def is_interactive(): import __main__ as main return not hasattr(main, '__file__')
Ich habe diese Methode als sehr nützlich empfunden, da ich viel Prototyping im Notebook mache. Zu Testzwecken verwende ich Standardparameter. Ansonsten lese ich die Parameter aus
sys.argv
.from sys import argv if is_interactive(): params = [<list of default parameters>] else: params = argv[1:]
Nach der Implementierung von
autonotebook
können Sie anhand des folgenden Codes feststellen, ob Sie sich in einem Notizbuch befinden.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
quelle
is_interactive()
unterscheidet nicht zwischen Notebook und Konsole.%run
von ipython ausgibt, ist nicht interaktiv. Man könnte argumentieren, dass es so sein sollte, aber es ist immer noch ein Gotcha.is_interactive
) scheint mir für die Frage grundsätzlich irrelevant zu sein. Es ist auch von zweifelhafter Korrektheit; Wie @marscher betont, zählt alles, was ausgeführt wird,python -c
als "interaktiv", obwohl dies nicht der Fall ist. Ich möchte es nicht selbst tun, da es nicht meine Antwort ist, aber ich denke, dies würde durch einfaches Löschen der gesamten ersten Hälfte der Antwort verbessert.Kürzlich bin ich auf einen Fehler im Jupyter-Notizbuch gestoßen, der eine Problemumgehung erfordert, und ich wollte dies tun, ohne die Funktionalität in anderen Shells zu verlieren. Ich habe festgestellt, dass die Lösung von keflavich in diesem Fall nicht funktioniert, da
get_ipython()
sie nur direkt vom Notebook und nicht von importierten Modulen verfügbar ist. So habe ich einen Weg gefunden, anhand meines Moduls 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 willkommen, wenn dies robust genug ist.
Auf ähnliche Weise können Sie auch Informationen zum Client und zur IPython-Version abrufen:
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']
quelle
'Ipython' in sys.modules
ausgewertetFalse
. Vielleicht meinst du'IPython' in sys.modules
? Dies istTrue
in meiner Jupyter-Umgebung. Dassys.modules
Wörterbuch enthält auch nicht den'ipykernel'
Schlüssel - wenn es in einem Notizbuch ausgeführt wird.Getestet auf Python 3.7.3
CPython-Implementierungen haben den Namen
__builtins__
übrigens als Teil ihrer Globals verfügbar. kann von der Funktion globals () abgerufen werden.Wenn ein Skript in einer Ipython-Umgebung ausgeführt wird,
__IPYTHON__
sollte dies ein Attribut von sein__builtins__
.Der folgende Code wird daher zurückgegeben,
True
wenn er unter Ipython ausgeführt wird oder wenn er angezeigt wirdFalse
hasattr(__builtins__,'__IPYTHON__')
quelle
Im Folgenden werden die Fälle von https://stackoverflow.com/a/50234148/1491619 erfasst, ohne dass die Ausgabe von analysiert werden muss
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
quelle
jupyter
ob es einjupyter console
,jupyter qtconsole
oderjupyter notebook
.Ich würde empfehlen, das Erkennen eines bestimmten Frontends zu vermeiden, da es zu viele davon 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 not None
Oben wird zurückgegeben,
False
wenn Sie über dierunning_from_ipython
übliche Python-Befehlszeile aufrufen . Wenn Sie es über Jupyter Notebook, JupyterHub, iPython Shell, Google Colab usw. aufrufen, wird es zurückgegebenTrue
.quelle
get_ipython()
kehrt es zurück<ipykernel.zmqshell.ZMQInteractiveShell at 0x7f750ba94320>
.get_ipython() is not None
zurückTrue
.Sie müssen lediglich diese beiden Zellen am Anfang Ihres Notizbuchs platzieren:
Zelle 1: (markiert als "Code"):
is_notebook = True
Zelle 2: (markiert als "Raw NBConvert"):
is_notebook = False
Die erste Zelle wird immer ausgeführt, die zweite Zelle wird jedoch nur ausgeführt, wenn Sie das Notizbuch als Python-Skript exportieren.
Später können Sie überprüfen:
if is_notebook: notebook_code() else: script_code()
Hoffe das hilft.
quelle
Wie wäre es mit so etwas:
import sys inJupyter = sys.argv[-1].endswith('json') print(inJupyter);
quelle
Soweit ich weiß, hat Here 3 Arten von Ipython verwendet
ipykernel
ipython qtconsole
(kurz "qtipython")Verwendung
'spyder' in sys.modules
kann Spyder unterscheidenaber für qtipython und jn ist die Ursache schwer zu unterscheiden
Sie haben die
sys.modules
gleiche IPython-Konfiguration:get_ipython().config
Ich finde einen Unterschied zwischen qtipython und jn:
Beim ersten Ausführen
os.getpid()
in der IPython-Shell wird die PID-Nummer abgerufendann renne
ps -ef|grep [pid number]
meine 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
meine 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 ipython. Der json-Name von jn ist länger als der von qtipython
Daher können wir alle Python-Umgebungen automatisch anhand des folgenden Codes 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 Spyder, Jupyter Notebook, Qtconsole.py
quelle
Ich verwende Django Shell Plus, um IPython zu starten, und wollte "In Notebook ausführen" als Django-Einstellungswert verfügbar machen.
get_ipython()
ist beim Laden von Einstellungen nicht verfügbar, daher verwende ich diese (die nicht kugelsicher ist, aber für die lokalen Entwicklungsumgebungen, in denen sie verwendet wird, gut genug ist):import sys if '--notebook' in sys.argv: ENVIRONMENT = "notebook" else: ENVIRONMENT = "dev"
quelle
Angenommen, Sie haben die Kontrolle über das Jupyter-Notizbuch, könnten Sie:
Legen Sie einen Umgebungswert in einer Zelle fest, der diesen Wert als Flag in Ihrem Code verwendet . Fügen Sie einen eindeutigen Kommentar in diese Zelle ein (oder in alle Zellen, die Sie ausschließen möchten).
# exclude_from_export
% set_env is_jupyter = 1
Exportieren Sie das Notizbuch als Python-Skript, um es in einem anderen Kontext zu verwenden. Der Export würde die kommentierten Zellen und anschließend den Code ausschließen, der den Umgebungswert festlegt. Hinweis: Ersetzen Sie your_notebook.ipynb durch den Namen Ihrer tatsächlichen Notebook-Datei.
jupyter nbconvert --to script --RegexRemovePreprocessor.patterns = "['^ # exclude_from_export']" your_notebook.ipynb
Dadurch wird eine Datei generiert, für die das Jupyter-Umgebungsflag nicht gesetzt ist. Dies ermöglicht Code, der es zur deterministischen Ausführung verwendet.
quelle