Geçerli IPython / Jupyter Not Defteri adını nasıl alırım


87

IPython dizüstü bilgisayarı çalıştırırken mevcut NoteBook adını almaya çalışıyorum. Defterin üstünde görebildiğimi biliyorum. Gibi bir şeyin peşindeyim

currentNotebook = IPython.foo.bar.notebookname()

Adı bir değişkende almam gerekiyor.


Onunla ne yapmaya çalışıyorsun? Tasarım gereği, çekirdek (kodu çalıştıran bit) ön ucu (not defterlerini açan bit) bilmiyor.
Thomas K

7
Merhaba, dizüstü bilgisayarı lateks / pdf oluşturma sürecini otomatikleştirmek için nbconvert ile kullanmak istiyorum. Defterlerim uzaktan çalışıyor. Bir dersten sonra öğrenciler sonuçlarının pdf sürümünü indirebilirler.
Tooblippe

1
P.Toccaceli'nin cevabı , JupyterLab'ın (1.1.4) (defter 5.6.0) son sürümleriyle uyumludur ve javascript gerektirmez.
joelostblom


Bazıları işi yaptı ve bir pip paketi yaptı: pypi.org/project/ipynbname kurulumupip install ipynbname
NeoTT

Yanıtlar:


26

Daha önce de belirtildiği gibi muhtemelen bunu yapamayacaksın, ama bir yolunu buldum. Bu alevli bir hack, bu yüzden buna hiç güvenmeyin:

import json
import os
import urllib2
import IPython
from IPython.lib import kernel
connection_file_path = kernel.get_connection_file()
connection_file = os.path.basename(connection_file_path)
kernel_id = connection_file.split('-', 1)[1].split('.')[0]

# Updated answer with semi-solutions for both IPython 2.x and IPython < 2.x
if IPython.version_info[0] < 2:
    ## Not sure if it's even possible to get the port for the
    ## notebook app; so just using the default...
    notebooks = json.load(urllib2.urlopen('http://127.0.0.1:8888/notebooks'))
    for nb in notebooks:
        if nb['kernel_id'] == kernel_id:
            print nb['name']
            break
else:
    sessions = json.load(urllib2.urlopen('http://127.0.0.1:8888/api/sessions'))
    for sess in sessions:
        if sess['kernel']['id'] == kernel_id:
            print sess['notebook']['name']
            break

Cevabımı IPython 2.0'da en azından basit bir testle "çalışan" bir çözümü içerecek şekilde güncelledim. Aynı çekirdeğe bağlı birden fazla dizüstü bilgisayar varsa, muhtemelen doğru cevabı vermenin garantisi yoktur.


connection_file_path = kernel.get_connection_file () artık çalışmıyor, dosya adı gerekli arg.
Purrell

2
Bazı güncellemeler: from IPython.lib import kernelŞu an yerine sadece from IPython import kernel. Ayrıca sözlüklerde 'isim' anahtarını kullanmak yerine, anahtar '
Tristan Reid

1
Yanıtlayanın kendisinin de belirttiği gibi, bu yanıt en son IPython için işe yaramıyor. Python 3.5'te
mbdevpl

1
4.3.0 sürümünden itibaren, bir kimlik doğrulama belirteci sağlamanız gerekir. Bu, kullanılarak alınabilir notebook.notebookapp.list_running_servers().
17:11 de yingted

1
Çalışan birden fazla sunucunuz varsa, çekirdeğin ana işleminin hangi bağlantı noktasını dinlediğini kontrol edebilirsiniz, bu size hangi sunucuya bağlanacağınızı söyleyecektir (veya her yerel Jupyter sunucusuna bağlanıp çekirdeğinizi çalıştıranların hangisi olduğunu kontrol edebilirsiniz).
yingted

41

IPython 2.0 ile çalışan aşağıdakilere sahibim. Ben defterin adı özelliğinin değeri olarak saklanır gözlemlenmiştir 'data-notebook-name'içinde <body>sayfanın etiketinin. Bu nedenle fikir, ilk olarak Javascript'ten --javascripts %%javascriptsihir sayesinde bir kod çözücüsünden çağrılabilir özelliğini almasını istemektir . Ardından, Python değişkenini ayarlayan bir komutla Python Kernel'e yapılan bir çağrı yoluyla Javascript değişkenine erişmek mümkündür. Bu son değişken çekirdekten bilindiği için diğer hücrelerden de erişilebilir.

%%javascript
var kernel = IPython.notebook.kernel;
var body = document.body,  
    attribs = body.attributes;
var command = "theNotebook = " + "'"+attribs['data-notebook-name'].value+"'";
kernel.execute(command);

Bir Python kod hücresinden

print(theNotebook)

Çıkış []: HowToGetTheNameOfTheNoteBook.ipynb

Bu çözümdeki bir kusur, bir defterin başlığını (adını) değiştirdiğinde, bu adın hemen güncellenmemesi (muhtemelen bir tür önbellek vardır) ve dizüstü bilgisayara erişmek için not defterini yeniden yüklemenin gerekmesidir. yeni isim.

[Düzenle] Düşünüldüğünde, daha verimli bir çözüm, <body>etiket yerine not defterinin adı için giriş alanını aramaktır. Kaynağa bakıldığında, bu alanın "not defteri_adı" kimliğine sahip olduğu görülmektedir. Daha sonra bu değeri a ile yakalamak document.getElementById()ve ardından yukarıdaki ile aynı yaklaşımı izlemek mümkündür . Kod, hala javascript büyüsünü kullanıyor

%%javascript
var kernel = IPython.notebook.kernel;
var thename = window.document.getElementById("notebook_name").innerHTML;
var command = "theNotebook = " + "'"+thename+"'";
kernel.execute(command);

Ardından, bir ipython hücresinden

In [11]: print(theNotebook)
Out [11]: HowToGetTheNameOfTheNoteBookSolBis

İlk çözümün aksine, dizüstü bilgisayarın adında yapılan değişiklikler anında güncellenir ve not defterini yenilemeye gerek yoktur.


Belki bir şeyi kaçırmışımdır, ancak javascript kodunu python'dan nasıl çağırırsınız?
Artjom B.

7
Ayrıca, javascript'idef getname(): display(Javascript('IPython.notebook.kernel.execute("theNotebook = " + "\'"+IPython.notebook.notebook_name+"\'");'))
Jakob

Dizüstü bilgisayarın yolunu bulmak için bunu nasıl değiştirebilirim?
Pedro M Duarte

@PedroMDuarte: Bu değeri elde etmek için javascript'teki IPython.notebook.notebook_path 'thename' için yukarıdaki komut dosyasını kullanabilirsiniz.
Tristan Reid

1
JS hilesi olmadan not defteri yolunu elde etmek için:globals()['_dh'][0]
germ

38

önceki cevaplara eklemek,

not defteri adını almak için bir hücrede aşağıdakileri çalıştırın:

%%javascript
IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')

bu size nb_name'deki dosya adını verir

daha sonra tam yolu elde etmek için aşağıdakileri ayrı bir hücrede kullanabilirsiniz:

import os
nb_full_path = os.path.join(os.getcwd(), nb_name)

1
IPython.notebook.notebook_nameBunu kullanmak şu şekilde yapılabilir%%javascript IPython.notebook.kernel.execute('notebookName = ' + '"' + IPython.notebook.notebook_name + '"')
jfb

10
Bazı nedenlerden dolayı, bu yalnızca javascript hücresini "el ile" çalıştırırsam çalışır. Defterin tamamını çalıştırırsam, ikinci hücre başarısız olur. Herhangi bir fikrin neden?
Pierre-Antoine

Sanırım bir nedenden ötürü, bir değişken javascript'ten değiştirilirse ve aynı çağrıda saf python'dan erişilirse, python sürümü güncellemeyi görmez ve aynı zamanda javascript sürümünün yerini alır. Sanırım javascript hücresini en üste taşıyabilir, çalıştırabilir ve ardından "Hücre> Tümünü Körüğü Çalıştır" seçeneğini kullanabilirsiniz.
Mahmoud Elagdar

2
Neden javascript'e ihtiyacımız var? daha yerli değil mi?
matanster

2
Jupyter Lab'de başarısız:Javascript Error: IPython is not defined
magicrebirth

27

Jupyter 3.0'da aşağıdaki çalışır. Burada sadece not defteri adını değil, Jupyter sunucusundaki tüm yolu gösteriyorum:

NOTEBOOK_FULL_PATHMevcut dizüstü bilgisayar ön ucunda saklamak için :

%%javascript
var nb = IPython.notebook;
var kernel = IPython.notebook.kernel;
var command = "NOTEBOOK_FULL_PATH = '" + nb.base_url + nb.notebook_path + "'";
kernel.execute(command);

Daha sonra görüntülemek için:

print("NOTEBOOK_FULL_PATH:\n", NOTEBOOK_FULL_PATH)

İlk Javascript hücresini çalıştırmak çıktı üretmez. İkinci Python hücresini çalıştırmak aşağıdaki gibi bir şey üretir:

NOTEBOOK_FULL_PATH:
 /user/zeph/GetNotebookName.ipynb

4
Bu çok temiz. O halde Javascript kodunu bir Python işlevinden nasıl çağırırsınız?
Lukas,

Hmmmm ... belki bu durumda bağlantı noktasını iki nokta üst üste ve ardından bağlantı noktası numarasıyla eklemelisiniz?
Zephaniah Grunschlag

3
Bu göreceli yol tam yol değil
Ivelin

Bu, ayarını da içermez c.NotebookApp.notebook_dir.
sappjw

4
Alıyorum Javascript Error: IPython is not defined. IPython'u javascript için nasıl yükleyebilirim
zozo

26

Görünüşe göre yorum yapamam, bu yüzden bunu bir cevap olarak göndermem gerekiyor.

@İguananaut tarafından kabul edilen çözüm ve @mbdevpl tarafından yapılan güncelleme, Notebook'un son sürümlerinde çalışmıyor gibi görünüyor. Aşağıda gösterildiği gibi düzelttim. Python v3.6.1 + Notebook v5.0.0 ve Python v3.6.5 ve Notebook v5.5.0'da kontrol ettim.

from notebook import notebookapp
import urllib
import json
import os
import ipykernel

def notebook_path():
    """Returns the absolute path of the Notebook or None if it cannot be determined
    NOTE: works only when the security is token-based or there is also no password
    """
    connection_file = os.path.basename(ipykernel.get_connection_file())
    kernel_id = connection_file.split('-', 1)[1].split('.')[0]

    for srv in notebookapp.list_running_servers():
        try:
            if srv['token']=='' and not srv['password']:  # No token and no password, ahem...
                req = urllib.request.urlopen(srv['url']+'api/sessions')
            else:
                req = urllib.request.urlopen(srv['url']+'api/sessions?token='+srv['token'])
            sessions = json.load(req)
            for sess in sessions:
                if sess['kernel']['id'] == kernel_id:
                    return os.path.join(srv['notebook_dir'],sess['notebook']['path'])
        except:
            pass  # There may be stale entries in the runtime directory 
    return None

Doküman dizesinde belirtildiği gibi, bu yalnızca kimlik doğrulama olmadığında veya kimlik doğrulaması belirteç tabanlı olduğunda çalışır.

Başkaları tarafından da bildirildiği gibi, Javascript tabanlı yöntemin, benim için bir anlaşma bozan bir "Tüm hücreleri çalıştır" (ancak hücreleri "manuel olarak" yürütürken çalışır) yürütürken çalışmadığını unutmayın.


Bunun için herhangi bir kütüphane var mı?
matanster

Javascript yöntemlerinin başarısızlığı benim için de bir anlaşma kırıcı oldu. Bu alternatifi gönderdiğiniz için teşekkürler!
gumption

Srv ['notebook_dir'] 'i jupyter_core.paths ile değiştirmem gerekiyor import jupyter_config_dir; traitlets.config'den import Config; c = Yapılandır (); file_path = os.path.join (jupyter_config_dir (), 'jupyter_notebook_config.py'); exec (open (file_path) .read ()); root_dir = c ['FileContentsManager'] ['root_dir']
Dave Babbitt

15

İpyparams paketi oldukça kolay bir şekilde yapabilirsiniz.

import ipyparams
currentNotebook = ipyparams.notebook_name

1
Bu, en üstte kabul edilen cevaptan daha iyi bir cevap gibi görünüyor.
alejandro

1

Jupyter Notebook sunucusunun ana bilgisayarına, bağlantı noktasına ve kimlik doğrulama jetonuna sahip olduğunuzu varsayarsak, bu sizin için çalışmalıdır. Bu cevaba dayanmaktadır .

import os
import json
import posixpath
import subprocess
import urllib.request
import psutil

def get_notebook_path(host, port, token):
    process_id = os.getpid();
    notebooks = get_running_notebooks(host, port, token)
    for notebook in notebooks:
        if process_id in notebook['process_ids']:
            return notebook['path']

def get_running_notebooks(host, port, token):
    sessions_url = posixpath.join('http://%s:%d' % (host, port), 'api', 'sessions')
    sessions_url += f'?token={token}'
    response = urllib.request.urlopen(sessions_url).read()
    res = json.loads(response)
    notebooks = [{'kernel_id': notebook['kernel']['id'],
                  'path': notebook['notebook']['path'],
                  'process_ids': get_process_ids(notebook['kernel']['id'])} for notebook in res]
    return notebooks

def get_process_ids(name):
    child = subprocess.Popen(['pgrep', '-f', name], stdout=subprocess.PIPE, shell=False)
    response = child.communicate()[0]
    return [int(pid) for pid in response.split()]

Örnek kullanım:

get_notebook_path('127.0.0.1', 17004, '344eb91bee5742a8501cc8ee84043d0af07d42e7135bed90')

0

Dizüstü bilgisayar sunucum değişebileceğinden bir başka hacky çözüm. Temel olarak rastgele bir dize yazdırır, kaydeder ve ardından bu dizeyi içeren bir dosyayı çalışma dizininde ararsınız. Save_checkpoint eşzamansız olduğu için süre gereklidir.

from time import sleep
from IPython.display import display, Javascript
import subprocess
import os
import uuid

def get_notebook_path_and_save():
    magic = str(uuid.uuid1()).replace('-', '')
    print(magic)
    # saves it (ctrl+S)
    display(Javascript('IPython.notebook.save_checkpoint();'))
    nb_name = None
    while nb_name is None:
        try:
            sleep(0.1)
            nb_name = subprocess.check_output(f'grep -l {magic} *.ipynb', shell=True).decode().strip()
        except:
            pass
    return os.path.join(os.getcwd(), nb_name)

0

Aynı anda birden fazla hücre çalıştırırsak, tüm Json tabanlı çözümler başarısız olur, çünkü sonuç yürütme bitene kadar hazır olmayacaktır (bu, uyku veya bekleme meselesi değildir, kendiniz kontrol edin, ancak çekirdeği yeniden başlatmayı unutmayın. ve her testi çalıştırın)

Önceki çözümlere dayanarak, bu, başka bir kodun ortasına koymanız gerekebileceği için %% sihrini kullanmaktan kaçınır:

from IPython.display import display, Javascript

# can have comments here :)
js_cmd = 'IPython.notebook.kernel.execute(\'nb_name = "\' + IPython.notebook.notebook_name + \'"\')'
display(Javascript(js_cmd))

Python 3 için, aşağıdakiler @Iguananaut tarafından verilen cevaba göre ve en son python ve muhtemelen birden çok sunucu için güncellenmiş:

import os
import json
try:
    from urllib2 import urlopen
except:
    from urllib.request import urlopen
import ipykernel

connection_file_path = ipykernel.get_connection_file()
connection_file = os.path.basename(connection_file_path)
kernel_id = connection_file.split('-', 1)[1].split('.')[0]    
    
running_servers = !jupyter notebook list
running_servers = [s.split('::')[0].strip() for s in running_servers[1:]]
nb_name = '???'
for serv in running_servers:
    uri_parts = serv.split('?')
    uri_parts[0] += 'api/sessions'
    sessions = json.load(urlopen('?'.join(uri_parts)))
    for sess in sessions:
        if sess['kernel']['id'] == kernel_id:
            nb_name = os.path.basename(sess['notebook']['path'])
            break
    if nb_name != '???':
        break
print (f'[{nb_name}]')
    
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.