Mam przykład kodu w Pythonie, który chciałbym udostępnić, który powinien zrobić coś innego, jeśli zostanie wykonany w terminalu Python / IPython lub w notatniku IPython.
Jak mogę sprawdzić na podstawie mojego kodu Pythona, czy działa on w notatniku IPython?
python
ipython
ipython-notebook
Christoph
źródło
źródło
Odpowiedzi:
Pytanie brzmi, co chcesz wykonać inaczej.
Robimy co w naszej mocy w IPythonie, aby jądro nie wiedziało, do jakiego typu frontendu jest podłączone, a właściwie możesz nawet mieć jądro podłączone do wielu różnych frontendów w tym samym czasie. Nawet jeśli możesz
stderr/out
rzucić okiem na typ, aby wiedzieć, czy jesteś w jądrze ZMQ, czy nie, nie gwarantuje to tego, co masz po drugiej stronie. Możesz nawet nie mieć żadnych frontendów.Prawdopodobnie powinieneś napisać swój kod w sposób niezależny od frontendu, ale jeśli chcesz wyświetlać różne rzeczy, możesz użyć bogatego systemu wyświetlania (link przypięty do wersji 4.x IPythona), aby wyświetlić różne rzeczy w zależności od frontendu, ale frontend wybierze, a nie biblioteka.
źródło
\x1b[A
(przesuń w górę), więc nie można drukować zagnieżdżonych słupków . Nie ma problemu z ipywidgets , możemy użyć natywnych widżetów Jupyter do wyświetlania pasków postępu. Ale mamy dwa różne sposoby wyświetlania paska postępu, a aplikacja może chcieć wiedzieć, jakie jest środowisko wyświetlania, aby dostosować i wydrukować zgodny pasek.%matplotlib inline
gdy działa jako notebook, ale nie w terminalu, ponieważ nie jest to potrzebne.Na moje potrzeby działały:
Powraca
'TerminalInteractiveShell'
na terminalowym IPythonie,'ZMQInteractiveShell'
na Jupyter (notebook AND qtconsole) i kończy się niepowodzeniem (NameError
) na zwykłym interpreterze Pythona.get_python()
Wydaje się, że metoda jest domyślnie dostępna w globalnej przestrzeni nazw podczas uruchamiania IPythona.Opakowanie w prostą funkcję:
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
Powyższe zostało przetestowane z Python 3.5.2, IPython 5.1.0 i Jupyter 4.2.1 na macOS 10.12 i Ubuntu 14.04.4 LTS
źródło
jupyter console
niestetyget_ipython()
zwraca instancjęZMQInteractiveShell
takżeget_ipython().__class__.__module__ == "google.colab._shell"
test.py
a następnie uruchomięfrom test import isnotebook; print(isnotebook())
w notatniku Jupyter, zostanie wydrukowanaTrue
. (Testowane na serwerach Notebook w wersjach 5.2.1 i 6.0.1.)Aby sprawdzić, czy jesteś w notatniku, co może być ważne np. Przy określaniu jakiego rodzaju paska postępu użyć, to zadziałało:
def in_ipynb(): try: cfg = get_ipython().config if cfg['IPKernelApp']['parent_appname'] == 'ipython-notebook': return True else: return False except NameError: return False
źródło
cfg['IPKernelApp']['parent_appname']
jest aIPython.config.loader.LazyConfigValue
, którego nie można porównaćTrue
z"iypthon-notebook"
IPython.kernel.zmq.zmqshell.ZMQInteractiveShell
instancję w ipynb (Jupyter) iIPython.terminal.interactiveshell.TerminalInteractiveShell
REPL w terminalu, na wypadek, gdybyś potrzebował rozróżnić między notebookami i terminalem / konsolami (co wpływa na drukowanie).try
bloku na:return str(type(get_ipython())) == "<class 'ipykernel.zmqshell.ZMQInteractiveShell'>"
shell='PyDevTerminalInteractiveShell'
podczas sprawdzania nazwy klasy.Możesz sprawdzić, czy Python jest w trybie interaktywnym za pomocą następującego fragmentu kodu [1] :
def is_interactive(): import __main__ as main return not hasattr(main, '__file__')
Uważam, że ta metoda jest bardzo przydatna, ponieważ wykonuję wiele prototypów w zeszycie. Do celów testowych używam parametrów domyślnych. W przeciwnym razie odczytałem parametry z
sys.argv
.from sys import argv if is_interactive(): params = [<list of default parameters>] else: params = argv[1:]
Po wdrożeniu
autonotebook
możesz stwierdzić, czy jesteś w notatniku, używając następującego kodu.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
źródło
is_interactive()
nie rozróżnia notebooka i konsoli.%run
z ipython jest nieinteraktywne. Można argumentować, że tak powinno być, ale wciąż jest to problem.is_interactive
) wydaje mi się zasadniczo nieistotna dla pytania. Jest to również wątpliwa poprawność; jak wskazuje @marscher, liczy wszystko, co zostało uruchomione,python -c
jako działające w trybie „interaktywnym”, nawet jeśli nie jest to prawdą. Nie chcę tego robić samodzielnie, ponieważ to nie moja odpowiedź, ale myślę, że można by to poprawić, usuwając po prostu całą pierwszą połowę odpowiedzi.Niedawno napotkałem błąd w notatniku Jupyter, który wymaga obejścia i chciałem to zrobić bez utraty funkcjonalności w innych powłokach. Zdałem sobie sprawę, że rozwiązanie keflavicha w tym przypadku nie działa, ponieważ
get_ipython()
jest dostępne tylko bezpośrednio z notebooka, a nie z importowanych modułów. Więc znalazłem sposób, aby wykryć z mojego modułu, czy jest importowany i używany z notebooka Jupyter, czy nie: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
Komentarze są mile widziane, jeśli jest to wystarczająco solidne.
W podobny sposób można uzyskać informacje o kliencie, a także o wersji IPythona:
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']
źródło
'Ipython' in sys.modules
oceniaFalse
. Może masz na myśli'IPython' in sys.modules
? To jestTrue
w moim środowisku Jupyter.sys.modules
Słowniku również nie zawiera'ipykernel'
klucz - gdy działa wewnątrz notebooka.Przetestowano pod kątem Pythona 3.7.3
Implementacje CPythona mają tę nazwę
__builtins__
dostępną jako część ich globali, które przy okazji. można pobrać za pomocą funkcji globals ().Jeśli skrypt działa w środowisku Ipython,
__IPYTHON__
powinien mieć atrybut__builtins__
.Dlatego poniższy kod zwraca,
True
jeśli jest uruchamiany pod Ipythonem lub podanyFalse
hasattr(__builtins__,'__IPYTHON__')
źródło
Poniższy opis przedstawia przypadki https://stackoverflow.com/a/50234148/1491619 bez konieczności analizowania danych wyjściowych
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
źródło
jupyter
, czy jest tojupyter console
,jupyter qtconsole
czyjupyter notebook
.Zalecałbym unikanie wykrywania określonego interfejsu, ponieważ jest ich zbyt wiele . Zamiast tego możesz po prostu sprawdzić, czy pracujesz w środowisku iPython:
def is_running_from_ipython(): from IPython import get_ipython return get_ipython() is not None
Powyższe zwróci,
False
jeśli wywołujeszrunning_from_ipython
ze zwykłego wiersza poleceń Pythona. Po wywołaniu go z Jupyter Notebook, JupyterHub, iPython shell, Google Colab itp., Wtedy powróciTrue
.źródło
get_ipython()
zwraca<ipykernel.zmqshell.ZMQInteractiveShell at 0x7f750ba94320>
.get_ipython() is not None
zwracaTrue
.Wszystko, co musisz zrobić, to umieścić te dwie komórki na początku swojego notatnika:
Komórka 1: (oznaczona jako „kod”):
is_notebook = True
Komórka 2: (oznaczona jako „Raw NBConvert”):
is_notebook = False
Pierwsza komórka będzie zawsze wykonywana, ale druga komórka zostanie wykonana tylko wtedy, gdy wyeksportujesz notatnik jako skrypt Pythona.
Później możesz sprawdzić:
if is_notebook: notebook_code() else: script_code()
Mam nadzieję że to pomoże.
źródło
Co powiesz na coś takiego:
import sys inJupyter = sys.argv[-1].endswith('json') print(inJupyter);
źródło
O ile wiem, tutaj są 3 rodzaje ipythonu, które zostały użyte
ipykernel
ipython qtconsole
(w skrócie „qtipython”)posługiwać się
'spyder' in sys.modules
pozwala odróżnić Spyderaale dla qtipython i jn są trudne do rozróżnienia
mają taką samą
sys.modules
i taką samą konfigurację IPythona:get_ipython().config
Znajduję różnicę między qtipython i jn:
pierwsze uruchomienie
os.getpid()
w powłoce IPython pobierz numer pidnastępnie uruchomić
ps -ef|grep [pid number]
mój numer pid qtipython to 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
mój pid jn to 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
różnica z qtipython i jn to nazwa json ipythona, nazwa jn jn jest dłuższa niż nazwa qtipython
więc możemy automatycznie wykryć całe środowisko Pythona, wykonując następujący kod:
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)
kod źródłowy jest tutaj: Detection Python Environment, szczególnie wyróżnia Spyder, Jupyter notebook, Qtconsole.py
źródło
Używam Django Shell Plus do uruchomienia IPython i chciałem, aby „praca w notebooku” była dostępna jako wartość ustawień Django.
get_ipython()
nie jest dostępny podczas ładowania ustawień, więc używam tego (co nie jest kuloodporne, ale wystarczająco dobre dla lokalnych środowisk programistycznych, w których jest używany):import sys if '--notebook' in sys.argv: ENVIRONMENT = "notebook" else: ENVIRONMENT = "dev"
źródło
Zakładając, że masz kontrolę nad notebookiem Jupyter, możesz:
ustaw wartość środowiska w komórce, która używa tego jako flagi w kodzie . Umieść unikalny komentarz w tej komórce (lub we wszystkich komórkach, które chcesz wykluczyć)
# exclude_from_export
% set_env is_jupyter = 1
Wyeksportuj notatnik jako skrypt w języku Python do użycia w innym kontekście. Eksport wykluczy skomentowane komórki, a następnie kod, który ustawia wartość środowiska. Uwaga: zastąp your_notebook.ipynb nazwą rzeczywistego pliku notatnika.
jupyter nbconvert --to script --RegexRemovePreprocessor.patterns = "['^ # exclude_from_export']" your_notebook.ipynb
Spowoduje to wygenerowanie pliku, który nie będzie miał ustawionej flagi środowiska jupyter, umożliwiającej kod, który używa jej do deterministycznego wykonywania.
źródło