Kodun IPython not defterinde çalıştırılıp çalıştırılmadığını nasıl kontrol edebilirim?


89

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?


3
Gustavo Bezerra'nın cevabını kabul etmenizi öneririm . Şu anda kabul edilen cevap soruyu cevaplamıyor ve Gustavonun cevabı Jupyter Notebook'un en son sürümünde hala çalışan en yüksek puanlı cevap.
Mark Amery

Yanıtlar:


8

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/outBir 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.


2
Yukarıdaki IPython Zengin Görüntüleme Sistemine olan bağlantı kopmuştur. İşte mevcut belgelere bağlantı: ipython.org/ipython-doc/dev/config/integrating.html ve işte bazı harika örnekler için bir bağlantı: nbviewer.ipython.org/github/ipython/ipython/blob/master/ …
Who8MyLunch

2
Çizim modülümde buna benzer bir problemim var . Çizimleri kaydetmeye izin vermek için travis-ci için matplotlib.use ("Agg") çağrısını içeri aktarmam gerekiyor (bkz. Stackoverflow.com/questions/4706451/… ) Ancak bu , not defterinde bir uyarı oluşturuyor UserWarning: Bu matplotlib.use çağrısı () hiçbir etkisi yoktur çünkü arka uç zaten seçilmiştir; Bu nasıl çözülür?
Dr. Goulu

33
Bir örneğim var: ilerleme çubukları. Jupyter dizüstü bilgisayar terminal öykünücüsü, \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.
2016

2
örneğin, IPython yapılandırmasını her %matplotlib inlinezaman bir dizüstü bilgisayar gibi davrandığında çalışacak , ancak buna gerek olmadığı için bir terminalde çalışmayacak şekilde ayarlamak istiyorum .
Ciprian Tomoiagă

3
Bu tamamen geçerli bir görüş olsa da, bu cevap asıl soruyu ele almıyor. Ne kadar olmasını dilediğiniz önemli değil, aksi takdirde davranışta her zaman önemli olabilecek farklılıklar olacaktır.
Christopher Barber

72

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 NameErrornormal 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.


5
Açık jupyter consolemaalesef get_ipython()bir örneğini döndürür ZMQInteractiveShellda
Josh Bode

7
Birisi dizüstü bilgisayarın Google get_ipython().__class__.__module__ == "google.colab._shell"
Colab'da çalışıp

3
Bu yalnızca not defterindeki kod için işe yarar. İşlev içe aktarılmış bir pakette ise çalışmaz.
Christopher Barber

4
@ChristopherBarber Gördüğüm bu değil. Bu işlevi bir dosyaya yapıştırır ve test.pyardı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.)
Mark Amery

Benim için işe yaramayan bir durum olduğunu düşündüm ama maalesef detayları hatırlamıyorum. Belki artık bir sorun değil ya da sadece kafam karışmıştı.
Christopher Barber

41

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

6
Benim ipython-Notebook (ipython sürüm 3.1) olarak, cfg['IPKernelApp']['parent_appname']bir olduğunu IPython.config.loader.LazyConfigValuekarşılaştırmak etmeyen, Trueile"iypthon-notebook"
Dux

5
@juanjux get_ipython , dizüstü bilgisayarlar ve terminaller / konsollar arasında ayrım yapmanız gerektiğinde (bu, çizimi etkiler IPython.kernel.zmq.zmqshell.ZMQInteractiveShell) ipynb'de (Jupyter) bir örnek ve bir IPython.terminal.interactiveshell.TerminalInteractiveShellterminalde REPL döndürür .
ocaklar

4
^ bu nedenle trybloğun içini şu şekilde değiştirebilirsiniz :return str(type(get_ipython())) == "<class 'ipykernel.zmqshell.ZMQInteractiveShell'>"
user2561747

@Dux gibi, bu benim için çalışmıyor; Defterde bile her zaman yanlış döndürür. Bu cevabın bir tür tembel yapılandırma yükleme sisteminin getirilmesiyle geçerliliğini yitirdiğinden şüpheleniyorum.
Mark Amery

Ayrıca yapılandırmanızın boş bir dikte olarak geri gelebileceğini unutmayın, bu durumda KeyError'ı dış bloğa eklemeniz gerekir. Ancak, Gustavo Bezerra'nın cevabına göre kod kullanmak muhtemelen daha iyidir. Boş bir yapılandırma alsam da, shell='PyDevTerminalInteractiveShell'sınıf adını incelerken alıyorum .
hlongmore

29

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, autonotebookaş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

python -c "def is_interactive ():> main olarak import main > return değil hasattr (main, ' file ')> print is_interactive ()" True
marscher

3
is_interactive()dizüstü bilgisayar ve konsol arasında ayrım yapmaz.
krock

1
Bir başka uyarı, %runipython'dan bir yayınlamak etkileşimli değildir. Olması gerektiğini iddia edebilirsin, ama yine de bir gotcha.
dirkjot

Not defterinde prototipleme yapan diğerleri için, burada gösterilen Till'in yaklaşımının varyantı yararlı olabilir.
Wayne

Bu cevabın ikinci yarısı kullanışlıdır, ancak ilk yarısı (yaklaşık 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 -cdoğ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.
Mark Amery

17

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']

Hm, Fedora 23 Jupyter kullanıyorum ve orada 'Ipython' in sys.modulesdeğerlendiriyor False. Belki de demek istiyorsun 'IPython' in sys.modules? Bu Truebenim Jupyter ortamımda. sys.modulesSözlük da içermez 'ipykernel'anahtarı - bir dizüstü içine çalıştırırken.
maxschlepzig

2
Şu ana kadarki en iyi cevap bu, IMO. Kısa ve güzel.
danielpcox

3

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__')

2

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

Benim için bu sadece gösterir jupyterbir olup olmadığı jupyter console, jupyter qtconsoleya da jupyter notebook.
Luke Davis

2

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.


Benim için çalışmıyor - Bunu Python3 ile Ubuntu'daki Jupyter Notebook'ta denediğimde get_ipython()geri dönüyor <ipykernel.zmqshell.ZMQInteractiveShell at 0x7f750ba94320>.
kahramanı

Bu yaklaşımla ilgili sorun, OP'nin "IPython not defterinde çalışıyorsa Python kodumdan nasıl kontrol edebilirim ?" Sorusunu çözmemesidir. (vurgu benim). IPython kabuğu bir dizüstü bilgisayar değil, ancak PyCharm'daki Python Konsolumda çalıştırdığımda get_ipython() is not Nonegeri dönüyorum True.
hlongmore

hm, jupyter ile voila arasında koştuğumu nasıl anlarım?
ntg

2

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.


2

Bunun gibi bir şeye ne dersiniz:

import sys

inJupyter = sys.argv[-1].endswith('json')

print(inJupyter);

1

Bildiğim kadarıyla, burada kullanılan 3 tür ipython var ipykernel

  1. ipython qtconsole (kısaca "qtipython")
  2. IPython in spyder (kısaca "spyder")
  3. Jupyter not defterinde IPython (kısaca "jn")

kullanmak 'spyder' in sys.modulescasusları ayırt edebilir

ancak qtipython ve jn için nedeni ayırt etmek zordur

aynı sys.modulesve 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


0

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"

0

Jupyter Not Defterinin kontrolüne sahip olduğunuzu varsayarak şunları yapabilirsiniz:

  1. 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

  2. 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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.