Saya memiliki beberapa contoh kode Python yang ingin saya bagikan yang seharusnya melakukan sesuatu yang berbeda jika dijalankan di terminal Python / IPython atau di notebook IPython.
Bagaimana cara memeriksa dari kode Python saya jika berjalan di notebook IPython?
python
ipython
ipython-notebook
Christoph
sumber
sumber
Jawaban:
Pertanyaannya adalah apa yang ingin Anda lakukan secara berbeda.
Kami melakukan yang terbaik di IPython mencegah kernel mengetahui jenis frontend mana yang terhubung, dan sebenarnya Anda bahkan dapat memiliki kernel yang terhubung ke banyak frontend yang berbeda pada saat yang bersamaan. Bahkan jika Anda dapat mengintip jenis
stderr/out
untuk mengetahui apakah Anda menggunakan kernel ZMQ atau tidak, itu tidak menjamin Anda tentang apa yang Anda miliki di sisi lain. Anda bahkan bisa tidak memiliki frontend sama sekali.Anda mungkin harus menulis kode Anda secara independen frontend, tetapi jika Anda ingin menampilkan hal yang berbeda, Anda dapat menggunakan sistem tampilan yang kaya (tautan disematkan ke versi 4.x dari IPython) untuk menampilkan hal-hal yang berbeda tergantung pada frontend, tetapi frontend akan memilih, bukan perpustakaan.
sumber
\x1b[A
(bergerak ke atas), jadi tidak mungkin untuk mencetak bilah bersarang . Tidak masalah dengan ipywidgets , kami dapat menggunakan widget Jupyter asli untuk menampilkan bilah kemajuan. Tetapi kemudian kami memiliki dua cara berbeda untuk menampilkan bilah kemajuan, dan sebuah aplikasi mungkin ingin tahu apa itu lingkungan tampilan untuk menyesuaikan dan mencetak bilah yang kompatibel.%matplotlib inline
saat berfungsi sebagai notebook, tetapi tidak di terminal, karena itu tidak diperlukan.Berikut ini bekerja untuk kebutuhan saya:
Ia kembali
'TerminalInteractiveShell'
pada terminal IPython,'ZMQInteractiveShell'
pada Jupyter (notebook AND qtconsole) dan gagal (NameError
) pada interpreter Python biasa. Metode iniget_python()
tampaknya tersedia di namespace global secara default saat IPython dimulai.Membungkusnya dalam fungsi sederhana:
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
Di atas diuji dengan Python 3.5.2, IPython 5.1.0 dan Jupyter 4.2.1 di macOS 10.12 dan Ubuntu 14.04.4 LTS
sumber
jupyter console
, sayangnyaget_ipython()
mengembalikan contohZMQInteractiveShell
jugaget_ipython().__class__.__module__ == "google.colab._shell"
test.py
lalu menjalankannyafrom test import isnotebook; print(isnotebook())
di Notebook Jupyter, fungsi ini akan dicetakTrue
. (Diuji pada server Notebook versi 5.2.1 dan 6.0.1.)Untuk memeriksa apakah Anda menggunakan buku catatan, yang mungkin penting misalnya saat menentukan bilah kemajuan seperti apa yang akan digunakan, ini berhasil untuk saya:
def in_ipynb(): try: cfg = get_ipython().config if cfg['IPKernelApp']['parent_appname'] == 'ipython-notebook': return True else: return False except NameError: return False
sumber
cfg['IPKernelApp']['parent_appname']
adalahIPython.config.loader.LazyConfigValue
, yang tidak dapat dibandingkanTrue
dengan"iypthon-notebook"
IPython.kernel.zmq.zmqshell.ZMQInteractiveShell
instance di ipynb (Jupyter) danIPython.terminal.interactiveshell.TerminalInteractiveShell
di REPL terminal, jika Anda perlu membedakan antara notebook dan terminal / konsol (yang memengaruhi plotting).try
blok dengan:return str(type(get_ipython())) == "<class 'ipykernel.zmqshell.ZMQInteractiveShell'>"
shell='PyDevTerminalInteractiveShell'
saat memeriksa nama kelas.Anda dapat memeriksa apakah python dalam mode interaktif dengan cuplikan berikut [1] :
def is_interactive(): import __main__ as main return not hasattr(main, '__file__')
Saya menemukan metode ini sangat berguna karena saya melakukan banyak prototipe di notebook. Untuk tujuan pengujian, saya menggunakan parameter default. Jika tidak, saya membaca parameter dari
sys.argv
.from sys import argv if is_interactive(): params = [<list of default parameters>] else: params = argv[1:]
Setelah penerapan
autonotebook
, Anda dapat mengetahui apakah Anda berada di buku catatan menggunakan kode berikut.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
sumber
is_interactive()
tidak membedakan antara notebook dan konsol.%run
dari ipython adalah non-interaktif. Anda bisa membantahnya, tapi itu masih gotcha.is_interactive
) menurut saya pada dasarnya tidak relevan dengan pertanyaan itu. Ini juga kebenaran yang meragukan; seperti yang ditunjukkan @marscher, ini menghitung apa pun yang dijalankan menggunakanpython -c
mode "interaktif" meskipun ini tidak benar. Saya tidak ingin melakukannya sendiri karena ini bukan jawaban saya, tetapi saya pikir ini akan diperbaiki hanya dengan menghapus seluruh paruh pertama jawaban.Baru-baru ini saya menemukan bug di notebook Jupyter yang memerlukan solusi, dan saya ingin melakukan ini tanpa kehilangan fungsionalitas di shell lain. Saya menyadari bahwa solusi keflavich tidak berfungsi dalam kasus ini, karena
get_ipython()
hanya tersedia langsung dari notebook, dan bukan dari modul yang diimpor. Jadi saya menemukan cara untuk mendeteksi dari modul saya apakah itu diimpor dan digunakan dari notebook Jupyter atau tidak: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
Komentar akan dihargai jika ini cukup kuat.
Dengan cara serupa dimungkinkan untuk mendapatkan beberapa info tentang klien, dan versi IPython juga:
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']
sumber
'Ipython' in sys.modules
evaluasi keFalse
. Mungkin maksud Anda'IPython' in sys.modules
? Ini adaTrue
di lingkungan Jupyter saya. Thesys.modules
kamus juga tidak termasuk'ipykernel'
kunci - saat berjalan di dalam notebook.Diuji untuk python 3.7.3
Implementasi CPython memiliki nama yang
__builtins__
tersedia sebagai bagian dari global mereka yang btw. bisa diambil oleh function globals ().Jika skrip berjalan di lingkungan Ipython maka
__IPYTHON__
harus berupa atribut__builtins__
.Karena itu kode di bawah ini kembali
True
jika dijalankan di bawah Ipython atau yang diberikannyaFalse
hasattr(__builtins__,'__IPYTHON__')
sumber
Berikut ini adalah contoh kasus https://stackoverflow.com/a/50234148/1491619 tanpa perlu mengurai keluaran dari
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
sumber
jupyter
apakah itu adalahjupyter console
,jupyter qtconsole
, ataujupyter notebook
.Saya akan merekomendasikan untuk menghindari mendeteksi frontend tertentu karena jumlahnya terlalu banyak . Sebagai gantinya Anda bisa menguji apakah Anda menjalankan dari dalam lingkungan iPython:
def is_running_from_ipython(): from IPython import get_ipython return get_ipython() is not None
Di atas akan ditampilkan
False
jika Anda memanggilrunning_from_ipython
dari baris perintah python biasa. Ketika Anda memanggilnya dari Jupyter Notebook, JupyterHub, iPython shell, Google Colab dll maka itu akan kembaliTrue
.sumber
get_ipython()
kembali<ipykernel.zmqshell.ZMQInteractiveShell at 0x7f750ba94320>
.get_ipython() is not None
kembaliTrue
.Yang harus Anda lakukan adalah menempatkan kedua sel ini di awal buku catatan Anda:
Sel 1: (ditandai sebagai "kode"):
is_notebook = True
Sel 2: (ditandai sebagai "Raw NBConvert"):
is_notebook = False
Sel pertama akan selalu dijalankan, tetapi sel kedua hanya akan dijalankan saat Anda mengekspor notebook sebagai skrip Python.
Nanti, Anda bisa mengecek:
if is_notebook: notebook_code() else: script_code()
Semoga ini membantu.
sumber
Bagaimana dengan sesuatu yang seperti ini:
import sys inJupyter = sys.argv[-1].endswith('json') print(inJupyter);
sumber
Setahu saya disini ada 3 macam ipython yang digunakan
ipykernel
ipython qtconsole
("qtipython" singkatnya)penggunaan
'spyder' in sys.modules
dapat membedakan spydertapi untuk qtipython dan jn susah dibedakan penyebabnya
mereka memiliki
sys.modules
konfigurasi IPython yang sama dan sama:get_ipython().config
Saya menemukan perbedaan antara qtipython dan jn:
jalankan pertama
os.getpid()
di shell IPython dapatkan nomor pidlalu lari
ps -ef|grep [pid number]
pid qtipython saya adalah 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
jn pid saya adalah 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
perbedaan qtipython dan jn adalah nama json ipython, nama json jn lebih panjang dari qtipython
jadi, kita bisa otomatis mendeteksi semua Python Environment dengan kode berikut:
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)
kode sumbernya ada di sini: Deteksi Lingkungan Python, Terutama membedakan Spyder, notebook Jupyter, Qtconsole.py
sumber
Saya menggunakan Django Shell Plus untuk meluncurkan IPython, dan saya ingin membuat 'berjalan di buku catatan' tersedia sebagai nilai pengaturan Django.
get_ipython()
tidak tersedia saat memuat pengaturan, jadi saya menggunakan ini (yang tidak anti peluru, tapi cukup baik untuk lingkungan pengembangan lokal yang digunakannya):import sys if '--notebook' in sys.argv: ENVIRONMENT = "notebook" else: ENVIRONMENT = "dev"
sumber
Dengan asumsi Anda memiliki kendali atas Notebook Jupyter, Anda dapat:
setel nilai lingkungan dalam sel yang menggunakan ini sebagai bendera dalam kode Anda . Tempatkan komentar unik di sel itu (atau semua sel yang ingin Anda kecualikan)
# exclude_from_export
% set_env is_jupyter = 1
Ekspor notebook sebagai skrip python untuk digunakan dalam konteks berbeda. Ekspor akan mengecualikan sel yang diberi komentar dan selanjutnya kode yang menetapkan nilai lingkungan. Catatan: ganti buku_Anda.ipynb dengan nama file buku catatan Anda yang sebenarnya.
jupyter nbconvert --to script --RegexRemovePreprocessor.patterns = "['^ # exclude_from_export']" your_notebook.ipynb
Ini akan menghasilkan file yang tidak akan memiliki set flag lingkungan jupyter yang memungkinkan kode yang menggunakannya untuk mengeksekusi secara deterministik.
sumber