Python / IPython terminalinde veya IPython not defterinde çalıştırıldığında farklı bir şey yapması gereken bazı Python kod örneğim var.
IPython not defterinde çalışıp çalışmadığını Python kodumdan nasıl kontrol edebilirim?
Python / IPython terminalinde veya IPython not defterinde çalıştırıldığında farklı bir şey yapması gereken bazı Python kod örneğim var.
IPython not defterinde çalışıp çalışmadığını Python kodumdan nasıl kontrol edebilirim?
Yanıtlar:
Soru, neyi farklı şekilde yürütmek istediğinizdir.
IPython'da elimizden gelenin en iyisini yapıyoruz, çekirdeğin hangi tür ön uçlara bağlı olduğunu bilmesini önlüyoruz ve aslında aynı anda birçok farklı ön uca bağlı bir çekirdeğe sahip olabilirsiniz. stderr/out
Bir ZMQ çekirdeğinde olup olmadığınızı bilme türüne bir göz atsanız bile, diğer tarafta neye sahip olduğunuz konusunda sizi garanti etmez. Hiç ön ucunuz bile olmayabilir.
Muhtemelen kodunuzu ön uçtan bağımsız bir şekilde yazmalısınız, ancak farklı şeyler görüntülemek istiyorsanız, ön uca bağlı olarak farklı şeyler görüntülemek için zengin görüntüleme sistemini (IPython sürüm 4.x'e sabitlenmiş bağlantı) kullanabilirsiniz, ancak kitaplık değil, ön uç seçecektir.
\x1b[A
(yukarı taşı) gibi genişletilmiş terminal kontrol karakterlerini desteklemez , bu nedenle iç içe çubuklar yazdırmak mümkün değildir . İpywidgets ile sorun değil , ilerleme çubuklarını görüntülemek için yerel Jupyter widget'larını kullanabiliriz. Ancak bir ilerleme çubuğunu görüntülemenin iki farklı yolu var ve bir uygulama, uyumlu çubuğu uyarlamak ve yazdırmak için görüntüleme ortamının ne olduğunu bilmek isteyebilir.
%matplotlib inline
zaman bir dizüstü bilgisayar gibi davrandığında çalışacak , ancak buna gerek olmadığı için bir terminalde çalışmayacak şekilde ayarlamak istiyorum .
Aşağıdakiler ihtiyaçlarım için çalıştı:
get_ipython().__class__.__name__
Jupyter'de (dizüstü bilgisayar VE qtconsole) 'TerminalInteractiveShell'
bir terminal 'ZMQInteractiveShell'
IPython'da geri döner ve NameError
normal bir Python yorumlayıcısında başarısız olur ( ). Yöntemget_python()
, IPython başlatıldığında varsayılan olarak genel ad alanında kullanılabilir görünüyor.
Basit bir işlevle sarmak:
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
Yukarıdakiler, macOS 10.12 ve Ubuntu 14.04.4 LTS üzerinde Python 3.5.2, IPython 5.1.0 ve Jupyter 4.2.1 ile test edilmiştir.
jupyter console
maalesef get_ipython()
bir örneğini döndürür ZMQInteractiveShell
da
get_ipython().__class__.__module__ == "google.colab._shell"
test.py
ardından from test import isnotebook; print(isnotebook())
bir Jupyter Defterinde çalıştırırsam , yazdırır True
. (Dizüstü bilgisayar sunucusu 5.2.1 ve 6.0.1 sürümlerinde test edilmiştir.)
Bir not defterinde olup olmadığınızı kontrol etmek için, örneğin ne tür ilerleme çubuğunun kullanılacağını belirlerken önemli olabilir, bu benim için çalıştı:
def in_ipynb():
try:
cfg = get_ipython().config
if cfg['IPKernelApp']['parent_appname'] == 'ipython-notebook':
return True
else:
return False
except NameError:
return False
cfg['IPKernelApp']['parent_appname']
bir olduğunu IPython.config.loader.LazyConfigValue
karşılaştırmak etmeyen, True
ile"iypthon-notebook"
IPython.kernel.zmq.zmqshell.ZMQInteractiveShell
) ipynb'de (Jupyter) bir örnek ve bir IPython.terminal.interactiveshell.TerminalInteractiveShell
terminalde REPL döndürür .
try
bloğun içini şu şekilde değiştirebilirsiniz :return str(type(get_ipython())) == "<class 'ipykernel.zmqshell.ZMQInteractiveShell'>"
shell='PyDevTerminalInteractiveShell'
sınıf adını incelerken alıyorum .
Python'un etkileşimli modda olup olmadığını aşağıdaki kod parçacığı [1] ile kontrol edebilirsiniz :
def is_interactive():
import __main__ as main
return not hasattr(main, '__file__')
Bu yöntemi çok kullanışlı buldum çünkü dizüstü bilgisayarda çok sayıda prototipleme yapıyorum. Test amacıyla varsayılan parametreleri kullanıyorum. Aksi takdirde parametreleri okurum sys.argv
.
from sys import argv
if is_interactive():
params = [<list of default parameters>]
else:
params = argv[1:]
Uygulamasının ardından, autonotebook
aşağıdaki kodu kullanarak bir not defterinde olup olmadığınızı anlayabilirsiniz.
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
is_interactive()
dizüstü bilgisayar ve konsol arasında ayrım yapmaz.
%run
ipython'dan bir yayınlamak etkileşimli değildir. Olması gerektiğini iddia edebilirsin, ama yine de bir gotcha.
is_interactive
) bana temelde soruyla alakasız görünüyor. Ayrıca doğruluğu da şüphelidir; @marscher'in belirttiği gibi, bu python -c
doğru olmasa bile kullanılan her şeyi "etkileşimli" modda sayar . Cevabım olmadığı için bunu kendim yapmak istemiyorum, ancak cevabın ilk yarısının tamamını silerek bunun iyileştirilebileceğini düşünüyorum.
Son zamanlarda Jupyter not defterinde geçici çözüm gerektiren bir hatayla karşılaştım ve bunu diğer kabuklardaki işlevselliği kaybetmeden yapmak istedim. Keflavich'in çözümünün bu durumda işe yaramadığını fark ettim , çünkü get_ipython()
sadece doğrudan dizüstü bilgisayardan mevcut, ithal modüllerden değil. Bu yüzden modülümden bir Jupyter not defterinden içe aktarılıp kullanılmadığını tespit etmenin bir yolunu buldum:
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
Bu yeterince sağlamsa, yorumlar takdir edilmektedir.
Benzer şekilde, istemci ve IPython sürümü hakkında bilgi almak da mümkündür:
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']
'Ipython' in sys.modules
değerlendiriyor False
. Belki de demek istiyorsun 'IPython' in sys.modules
? Bu True
benim Jupyter ortamımda. sys.modules
Sözlük da içermez 'ipykernel'
anahtarı - bir dizüstü içine çalıştırırken.
Python 3.7.3 için test edildi
CPython uygulamaları, __builtins__
btw olan globallerinin bir parçası olarak kullanılabilir isme sahiptir. globals () işlevi tarafından alınabilir.
Bir komut dosyası bir Ipython ortamında çalışıyorsa, o __IPYTHON__
zaman bir özniteliği olmalıdır __builtins__
.
Bu nedenle aşağıdaki kod True
, Ipython altında çalıştırılırsa veyaFalse
hasattr(__builtins__,'__IPYTHON__')
Aşağıda, https://stackoverflow.com/a/50234148/1491619 durumlarını , çıkışını ayrıştırmaya gerek kalmadan yakalar :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
jupyter
bir olup olmadığı jupyter console
, jupyter qtconsole
ya da jupyter notebook
.
Belirli bir ön ucu tespit etmekten kaçınmanızı tavsiye ederim çünkü çok fazla var . Bunun yerine, iPython ortamından çalışıp çalışmadığınızı test edebilirsiniz:
def is_running_from_ipython():
from IPython import get_ipython
return get_ipython() is not None
Normal python komut satırından False
çağırıyorsanız, yukarı dönecektir running_from_ipython
. Jupyter Notebook, JupyterHub, iPython kabuğu, Google Colab vb.'den çağırdığınızda geri dönecektir True
.
get_ipython()
geri dönüyor <ipykernel.zmqshell.ZMQInteractiveShell at 0x7f750ba94320>
.
get_ipython() is not None
geri dönüyorum True
.
Tek yapmanız gereken, bu iki hücreyi defterinizin başına yerleştirmektir:
1. Hücre: ("kod" olarak işaretlenmiştir):
is_notebook = True
Hücre 2: ("Ham NBConvert" olarak işaretlenmiştir):
is_notebook = False
İlk hücre her zaman çalıştırılır, ancak ikinci hücre yalnızca not defterini bir Python betiği olarak dışa aktardığınızda çalıştırılır.
Daha sonra şunları kontrol edebilirsiniz:
if is_notebook:
notebook_code()
else:
script_code()
Bu yardımcı olur umarım.
Bunun gibi bir şeye ne dersiniz:
import sys
inJupyter = sys.argv[-1].endswith('json')
print(inJupyter);
Bildiğim kadarıyla, burada kullanılan 3 tür ipython var ipykernel
ipython qtconsole
(kısaca "qtipython")kullanmak 'spyder' in sys.modules
casusları ayırt edebilir
ancak qtipython ve jn için nedeni ayırt etmek zordur
aynı sys.modules
ve aynı IPython yapılandırmasına sahipler :get_ipython().config
Qtipython ve jn arasında farklı bir şey buluyorum:
ilk çalıştırma os.getpid()
IPython kabuğunda pid numarasını al
o zaman koş ps -ef|grep [pid number]
qtipython pid'im 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
benim jn pidim 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
qtipython ve jn'den farklı olan ipython'un json adıdır, jn'nin json adı qtipython'unkinden daha uzundur
bu nedenle, aşağıdaki kodu izleyerek tüm Python Ortamını otomatik olarak algılayabiliriz:
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)
kaynak kodu burada: Detection Python Environment, Özellikle Spyder, Jupyter notebook, Qtconsole.py ayırt edin
IPython'u başlatmak için Django Shell Plus kullanıyorum ve 'dizüstü bilgisayarda çalıştırma'yı Django ayarları değeri olarak kullanılabilir hale getirmek istedim. get_ipython()
ayarları yüklerken kullanılamıyor, bu yüzden bunu kullanıyorum (kurşun geçirmez değil, ancak kullanıldığı yerel geliştirme ortamları için yeterince iyi):
import sys
if '--notebook' in sys.argv:
ENVIRONMENT = "notebook"
else:
ENVIRONMENT = "dev"
Jupyter Not Defterinin kontrolüne sahip olduğunuzu varsayarak şunları yapabilirsiniz:
bunu kodunuzda bayrak olarak kullanan bir hücrede bir ortam değeri ayarlayın . Bu hücreye (veya hariç tutmak istediğiniz tüm hücrelere) benzersiz bir yorum yerleştirin
# exclude_from_export
% set_env is_jupyter = 1
Not defterini farklı bir bağlamda kullanılmak üzere bir python betiği olarak dışa aktarın. Dışa aktarma, yorum yapılan hücreleri ve ardından ortam değerini belirleyen kodu hariç tutar. Not: your_notebook.ipynb dosyasını değiştirin dosyasını gerçek not defteri dosyanızın adıyla .
jupyter nbconvert --to - komut dosyası --RegexRemovePreprocessor.patterns = "['^ # exclude_from_export']" your_notebook.ipynb
Bu, jupyter ortam bayrak setine sahip olmayacak bir dosya oluşturarak, onu belirleyici olarak çalıştırmak için kullanan koda izin verir.