[python] 현재 IPython / Jupyter 노트북 이름을 얻으려면 어떻게해야합니까?

IPython 노트북을 실행할 때 현재 메모장 이름을 얻으려고합니다. 노트북 상단에서 볼 수 있다는 것을 알고 있습니다. 내가 무엇을 추구하는지

currentNotebook = IPython.foo.bar.notebookname()

변수에 이름을 가져와야합니다.



답변

이미 언급했듯이 당신은 아마도 이것을 할 수 있어야하는 것은 아니지만 방법을 찾았습니다. 그것은 불타는 해킹이므로 전혀 의존하지 마십시오.

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

최소한 간단한 테스트로 IPython 2.0에서 “작동”하는 솔루션을 포함하도록 내 대답을 업데이트했습니다. 동일한 커널에 연결된 노트북이 여러 개인 경우 정답을 보장 할 수 없습니다.


답변

IPython 2.0에서 작동하는 다음이 있습니다. 나는 노트북의 이름 속성의 값으로 저장되는 것을 관찰 'data-notebook-name'에서 <body>페이지의 태그입니다. 따라서 아이디어는 먼저 Javascript에 속성을 검색하도록 요청하는 것입니다 %%javascript. 즉, 마술 덕분에 코드 셀에서 JavaScript를 호출 할 수 있습니다 . 그런 다음 Python 변수를 설정하는 명령을 사용하여 Python 커널에 대한 호출을 통해 Javascript 변수에 액세스 할 수 있습니다. 이 마지막 변수는 커널에서 알 수 있으므로 다른 셀에서도 액세스 할 수 있습니다.

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

Python 코드 셀에서

print(theNotebook)

Out [] : HowToGetTheNameOfTheNoteBook.ipynb

이 솔루션의 결함은 노트북의 제목 (이름)을 변경하면이 이름이 즉시 업데이트되지 않는 것처럼 보이고 (아마도 일종의 캐시가 있음) 노트북에 액세스하려면 노트북을 다시로드해야한다는 것입니다. 새로운 이름.

[편집] 리플렉션에서보다 효율적인 솔루션은 <body>태그 대신 노트북 이름 입력 필드를 찾는 것입니다 . 소스를 살펴보면이 필드에 “notebook_name”ID가있는 것으로 보입니다. 그러면이 값을 a로 포착 document.getElementById()한 다음 위와 동일한 접근 방식을 따를 수 있습니다. 코드는 여전히 자바 스크립트 마법을 사용합니다.

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

그런 다음 ipython 셀에서

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

첫 번째 솔루션과 달리 노트북 이름 수정은 즉시 업데이트되며 노트북을 새로 고칠 필요가 없습니다.


답변

이전 답변에 추가,

노트북 이름을 얻으려면 셀에서 다음을 실행하십시오.

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

이것은 nb_name의 파일 이름을 얻습니다.

그런 다음 전체 경로를 얻으려면 별도의 셀에서 다음을 사용할 수 있습니다.

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


답변

Jupyter 3.0에서는 다음이 작동합니다. 여기에서는 노트북 이름뿐만 아니라 Jupyter 서버의 전체 경로를 보여줍니다.

NOTEBOOK_FULL_PATH현재 노트북 프런트 엔드에을 저장하려면 :

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

그런 다음이를 표시하려면 :

print("NOTEBOOK_FULL_PATH:\n", NOTEBOOK_FULL_PATH)

첫 번째 Javascript 셀을 실행하면 출력이 생성되지 않습니다. 두 번째 Python 셀을 실행 하면 다음과 같은 결과가 생성됩니다.

NOTEBOOK_FULL_PATH:
 /user/zeph/GetNotebookName.ipynb


답변

댓글을 달 수없는 것 같아서 답변으로 게시해야합니다.

@iguananaut가 수락 한 솔루션과 @mbdevpl의 업데이트가 최신 버전의 노트북에서 작동하지 않는 것 같습니다. 아래와 같이 수정했습니다. Python v3.6.1 + Notebook v5.0.0과 Python v3.6.5 및 Notebook v5.5.0에서 확인했습니다.

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

독 스트링에 명시된 바와 같이 이는 인증이 없거나 인증이 토큰 기반 인 경우에만 작동합니다.

다른 사람들이보고 한 것처럼 Javascript 기반 메서드는 “모든 셀 실행”을 실행할 때 작동하지 않는 것 같지만 (그러나 셀을 “수동으로”실행할 때는 작동 함) 저에게 거래를 방해했습니다.


답변

ipyparams의 패키지는 아주 쉽게이 작업을 수행 할 수 있습니다.

import ipyparams
currentNotebook = ipyparams.notebook_name


답변

Jupyter Notebook 서버의 호스트, 포트 및 인증 토큰이 있다고 가정하면이 기능이 작동합니다. 이 답변을 기반으로합니다 .

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()]

사용 예 :

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