본문 바로가기
Development/for Machine Learning

Jupyter Notebook

by IMCOMKING 2017. 5. 23.

# Jupyter와 IPython의 관계: 

원래는 Jupyter와 IPython은 하나의 프로젝트 였음. 근데 notebook이 엄청 흥하면서 점차 프로젝트의 규모가 커졌음.

이에 Python이 아닌 다른 언어를 지원하기시작하고 더 잦은 업데이트가 필요한데 규모가 너무커서 힘들었음.

그래서 3.0버전까지는 하나의 통합된 IPython만 존재했는데, 이제부터는 쪼개서 jupyter라는 거대한 통합 플렛폼안에 소속된 프로젝트로 IPython이 들어가는 형식으로 쪼갰음.(즉 여러 언어중에 하나로 Python도 지원한다.)

http://blog.jupyter.org/2015/04/15/the-big-split/

 

현재 최신 jupyter notebook은 5.0 버전임.
https://github.com/jupyter/notebook/releases

 

그리고 이제 기존에 쓰던 IPython은 그냥 내부 파이썬 커널이되었음.
따라서 이제는 jupyter notebook 이라고 정확한 명칭을 불러야함!
http://jupyter-notebook.readthedocs.io/en/latest/

 

 

* Jupyter 버전 충돌시 문제 해결
pip3 freeze 로 나오는 jupyter / ipython / nb~ 관련된 모든 패키지를 삭제함.
apt-get remove 로도 마찬가지임.
그다음 아래 방법으로 설치

 

# Jupyter 간략 설치 및 실행방법
* 설치방법
sudo pip3 install -U jupyter

또는

sudo pip3 install notebook
또는
sudo conda install jupyter


* 설치 테스트
jupyter notebook
(위 명령어에서 에러가 생기면 pip install setuptools==33.1.1 을 실행https://jupyter.readthedocs.io/en/latest/install.html



 

- 실행방법
실제로 유용한 퍼블릭 웹서버로 하려면 다음으로 해야함.

python
from notebook.auth import passwd
passwd()
(Enter password:)
(Verify password:)


출력 예시 --> Out[2]: 'sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed'
(여기서 작은따옴표 안의 내용을 복사한다.)

 

* 그런데 위와 같이 이렇게 비밀번호 수동으로 안바꾸고 편하게 바꾸는 방법이 있음

 

jupyter notebook --generate-config 을 먼저 실행해서 default config를 생성하고

jupyter notebook password

이렇게 입력하면, 저절로 해당 비밀번호로 config파일에 덮어씌워진다.

 

vim ~/.jupyter/jupyter_notebook_config.py

(그다음 vim에서 /password 을 입력하여 #c.NotebookApp.password = 이라는 부분을 찾고, 우측부분에 아까 복사해둔 내용을 붙여넣기하고 #으로 된 주석을 제거한다.)
(vim 에서 찾기 기능: esc, /키워드, 엔터, n(next))

* 최근버전에서는 뭔가 sha1 대신, argon2라는 양식으로 바뀌었는데, 그냥 그대로 똑같이 사용 가능한 것으로 보인다.

 

c.NotebookApp.ip = '0.0.0.0'      ## "*" 보다 0.0.0.0이 호환성이 더크다

c.NotebookApp.open_browser = False
c.NotebookApp.port = 9999
c.NotebookApp.notebook_dir = '/home/~~~'

(마찬가지로 위의 3가지 항목도 위와 같이 바꿔준다. 이때 포트번호는 9999대신 다른것을 써도된다.)

그리고나서 다시 다음 명령어를 실행한다

sudo jupyter notebook

 

혹은

 

sudo jupyter notebook --allow-root --config="/home1/irteamsu/.jupyter/jupyter_notebook_config.py"

 

그러면 이제 웹서버가 실행이 되었고, 해당 리눅스 서버의 ip:8888로 접속할 수 있다.

* 추가로 screen을 이용해서 백그라운드에서 notebook서버를 돌리는 것과 포트포워딩을 통한 외부망 접속등이 필요할 수가 있다.

http://jupyter-notebook.readthedocs.io/en/latest/public_server.html

 
 
## 외부접속 허용 Trouble shooting
- no address associated with hostname. 에러가 발생시
jupyter_notebook_config.py에서 아래와 같이 수정해준다.
 
c.NotebookApp.allow_origin = '*' #allow all origins
c.NotebookApp.ip = '0.0.0.0' # listen on all IPs
https://stackoverflow.com/questions/42848130/why-i-cant-access-remote-jupyter-notebook-server
 
 
 
 
# Jupyter theme
- 기본 상태로 바꾸기: 가끔 검은화면에 이상한 테마가 적용될 때
jt -r
 
- 사용가능한 테마 리스트
jt -l
 
 
 

# Jupyter notebook에서 WSL(ubuntu)으로 파일 다운로드 받기

Jupyter 서버에 token이나 password가 걸려있지 않은 경우, 커맨드라인에서 바로 wget을 사용해 파일의 위치를 입력하면 다운받을 수 있다.
 
만약 python을 이용해 다운로드 받고 싶으면, urllib를 사용할 수 있다.
 

* Jupyter에 nbzip extension 설치하기

pip install nbzip
jupyter serverextension enable --py nbzip --sys-prefix
jupyter nbextension install --py nbzip
jupyter nbextension enable --py nbzip
 

* Terminal에서 zip명령어 이용해서 다운받기

zip -r filename.zip *.csv
 

* 서버에 token이나 password가 걸려 있는 경우: http.server우회

아주 신박한 방법을 소개한다. 이는 임시로 auth 제한이 없는 HTTP서버를 열어서 노트북의 권한문제 우회하는 방법이다.
 
1. Notebook을 하나 만든다.
2. 다음을 실행한다. 
 
!python3 -m http.server 8888 --directory /
이때 포트 번호 8888대신 임의의 번호를 사용해도 된다. <server_url>:8888 에 직접 접속하여 파일 목록을 확인할 수도 있다.
 
3. 다운로드 받고자 하는 위치에서 wget <server_url>:8888/path/to/file 을 입력하면 password나 token없이 바로 다운로드가 가능하다.
 
 
* 주의사항
가끔 wget을 실행시 403 error가 발생하는 경우가 있다. 그 이유는 DNS rebinding 어택을 막기위해 unknown origin으로부터의 request를 막아두었기 때문이다. 그러한 경우 아래의 옵션을 True로 바꿔주어야한다.
 
c.NotebookApp.allow_remote_access = True
 
 
 
 
 

# Jupyter Notebook의 다양한 display기능들

 

FileLink

FileLink를 사용하면, 브라우저에서 우클릭을 통해 다운로드 가능한 링크를 생성해준다.

 
 
 
# Nbextensions 사용하기
 
- 설치
sudo pip install jupyter_contrib_nbextensions
sudo jupyter contrib nbextension install --user
 
그다음 jupyter를 재시작 한다음 Nbextensions메뉴에서 원하는 기능을 키거나 혹은, 직접 수동으로 다음 명령어를 입력하여 기능 실행

jupyter nbextension enable init_cell/main
 

1. Table of Contents (2)

2. Initialization cells: 노트북을 restart 할 때 자동으로 실행할 cell들을 지정함.
jupyter nbextension enable init_cell/main

3. Scratchpad
 
4. Skip-Traceback
 

5. ExcuteTime

6. Notify
 
 

# Notebook을 pdf로 만들기

다음의 python 프로그램을 사용해서 html로 변환하고, WnvFreeHtmlToPdf을 이용해 pdf으로 변환한다.

wget https://gist.github.com/imcomking/625d41730fb94f2d176a9c903175e880/raw/7c24cec0fbf8846b7db436d3a09d66b19a76f46a/ipy2html.py
python ipy2html.py [notebook 이름]

https://github.com/jupyter/nbconvert/issues/699

 

* python 프로그램을 직접 만든 이유: https://github.com/jupyter/nbconvert/issues/699#issuecomment-385938801

nbconvert에서 공식으로 지원하는 html변환 기능을 사용하게 되면, html 문서뿐만이 아니라 노트북에 embed된 이미지가 html문서안에 포함된다. 그러나 이 방식은 clipboard로 부터 바로 embed를 할수 있도록 최근에 추가된 노트북 attachment:image.png 방식의 이미지를 embed하지 못한다. 그래서 attachment:image.png 방식의 이미지가 전부 깨져버리기 때문에 위의 ipy2html.py를 내가 직접 만든 것이다.

jupyter nbconvert --EmbedImagesPreprocessor.embed_remote_images=True --EmbedImagesPreprocessor.embed_images=True [my.ipynb]

http://jupyter-contrib-nbextensions.readthedocs.io/en/latest/exporting.html

https://nbconvert.readthedocs.io/en/latest/nbconvert_library.html#Extracting-Figures-using-the-HTML-Exporter

 

 

 

# Jupyter notebook 의 output이 너무 많아 열리지 않을 때, command line을 통해 output 제거하기
jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace Notebook.ipynb
jupyter nbconvert --ClearOutputPreprocessor.enabled=True --output=NotebookNoOut Notebook.ipynb

https://stackoverflow.com/questions/28908319/how-to-clear-an-ipython-notebooks-output-in-all-cells-from-the-linux-terminal

 

 

# Jupyter notebook 고급 tricks and tips
- Out 객체를 이용하면, 다른 cell들의 text output에 접근이 가능하다.

## Notebook에서 제공하는 다음의 특수 기능(magics)들을 활용할 수 있다.
http://ipython.readthedocs.io/en/stable/interactive/magics.html

- Available line magics:
%alias  %alias_magic  %autocall  %automagic  %autosave  %bookmark  %cat  %cd  %clear  %colors  %config  %connect_info  %cp  %debug  %dhist  %dirs  %doctest_mode  %ed  %edit  %env  %gui  %hist  %history  %killbgscripts  %ldir  %less  %lf  %lk  %ll  %load  %load_ext  %loadpy  %logoff  %logon  %logstart  %logstate  %logstop  %ls  %lsmagic  %lx  %macro  %magic  %man  %matplotlib  %mkdir  %more  %mv  %notebook  %page  %pastebin  %pdb  %pdef  %pdoc  %pfile  %pinfo  %pinfo2  %popd  %pprint  %precision  %profile  %prun  %psearch  %psource  %pushd  %pwd  %pycat  %pylab  %qtconsole  %quickref  %recall  %rehashx  %reload_ext  %rep  %rerun  %reset  %reset_selective  %rm  %rmdir  %run  %save  %sc  %set_env  %store  %sx  %system  %tb  %time  %timeit  %unalias  %unload_ext  %who  %who_ls  %whos  %xdel  %xmode

- Available cell magics: (if Automagic is ON, % prefix IS NOT needed for line magics.)
%%!  %%HTML  %%SVG  %%bash  %%capture  %%debug  %%file  %%html  %%javascript  %%js  %%latex  %%perl  %%prun  %%pypy  %%python  %%python2  %%python3  %%ruby  %%script  %%sh  %%svg  %%sx  %%system  %%time  %%timeit  %%writefile

# 설명
- %%! : system command
- %%capture [foo_var] : cell의 output 내용을 foo_var 파이썬 변수에 저장한다.


https://www.dataquest.io/blog/jupyter-notebook-tips-tricks-shortcuts/

 

 

# Jupyter notebook의 javascript 수정하기

Jupyter.notebook.get_selected_cell()
현재 선택된 cell의 javascript object를 가져온다.

Javascript object해킹: https://stackoverflow.com/questions/39613822/how-to-select-current-cell-with-javascript-in-jupyter

http://jupyter-notebook.readthedocs.io/en/stable/frontend_config.html

 

## 다른 api 확인을 위해선 github에 들어가야한다

Jupyter.notebook.move_selection_up()
현재 cell을 한칸 위로 올린다.

- get_selected_cell의 구현방식.

    Notebook.prototype.get_selected_cell = function () {
        var index = this.get_selected_index();
        return this.get_cell(index);
    };

https://github.com/jupyter/notebook/blob/master/notebook/static/notebook/js/notebook.js#L197-L210

 

 

## Notebook에 출력되는 html 형식 설정하기
- 어떤 클래스의 _repr_html_을 override하면 원하는 형식의 html을 지정할 수 있다.
class XX():
     def _repr_html_(self):
         #return '<img src='"http://placehold.it/200x300"'/>'
         return jscode + "<script>console.log('HELLO WORLD')</script>"

# XX()

 

 

# Notebook에서 Bokeh 사용하기
1) Trust로 바꾸기
https://bokeh.pydata.org/en/latest/docs/user_guide/notebook.html#trusting-notebooks

2) Handle 넘기기



## Jupyter Notebook Trust 하기

jupyter trust /path/to/notebook.ipynb

이를 입력하거나 또는 File 메뉴에서 Trust버튼을 눌러도 된다. 그러면 Trusted Notebook으로 메뉴가 바뀌고, 선택 불가능해진다. 이 상태에서는 임의의 javascript 코드가 실행되므로 보안에 유의해야한다. 

https://jupyter-notebook.readthedocs.io/en/latest/security.html
https://stackoverflow.com/questions/50311304/trusting-an-untrusted-notebook

 

 

# Jupyter 기능 100% 활용하기
- 다음 문서에는 전체 document가 작성되어있다.(web과 똑같은지 확인 필요)
https://media.readthedocs.org/pdf/testnb/latest/testnb.pdf

 

## notebook 파일에 javascript로 그려진 이미지를 직접 저장하기

이 내용은 상당히 고급 노트북 사용자를 위한 내용이다. 우선 ipython notebook은 모든 내용물을 json파일 형태로 저장하고, 주피터 서버에서 이를 파싱해서 렌더링하고 있다.

ex) {
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.6.2 |Anaconda, Inc.| (default, Oct  5 2017, 07:59:26) \n",
      "[GCC 7.2.0]\n",
      "User : KR18360 credit 991670\n"
     ]
    }
    ....

따라서 여기에 저장되지 않은 내용물은 언제든지 손실될 수 있는 정보이다. 그러나 재현 가능한 코드라면 언제든지 다시 결과물을 얻을 수 있을 수 있기 때문에, 일반적으로는 크게 걱정하지 않아도 된다.

그런데 문제는 코드의 재현 가능성이 특정한 이유로 보장되지 않는다면, 우리는 cell의 output결과를 모두 이 노트북안에 저장해야한다.

그러한 예시로 가장 크리티컬한 것이 바로 javascript로 그려진 이미지이다. Jupyter notebook에서는 보안상의 이슈로 모든 cell의 output을 먼저 clear 시키고, 아주 안전한 html과 markdown만을 다시 실행시킨다. 즉 javascript로 된 cell output은 모두 날아가버리는 보안 정책을 취하고 있다.

http://jupyter-notebook.readthedocs.io/en/stable/security.html#security-in-notebook-documents

물론 이를 강제로 실행하게끔 trust 옵션을 주는 방법도 있지만, 해당이미지를 그리기 위한 원본 그래프 데이터를 잃어버리게 되는 경우 복구할 방법이 없다.

따라서 javascript로 그려진 canvas이미지를 static하게 rasterize하는 기능이 필요하다. 이를 하는 방법은 크게 다음의 방법들을 검토해볼 수 있다.

1) Jupyter.notebook.get_cell 등의 API를 이용해 Javascript object를 가져와서 json에 데이터를 기록

나는 이 방식을 이용해 구현하는 데에 성공했으나 2,3번 의 경우 python api를 쓸 수 있다는 점에서 보다 편리한 구현이 가능할 수도 있다.

우선 notebook의 json을 javascript로 수정할 때 주의할 사항은 기본 형식에 맞게 수정해야만 정상적으로 save가 된다는 것이다. 잘못된 형식으로 저장을 하면 error가 뜨거나 저장할 때 경고문이 나온다.

https://github.com/jupyter/notebook/blob/master/notebook/static/notebook/js/notebook.js#L197-L210

이를 이용해 구현한 소스코드는 다음과 같다.

https://gist.github.com/imcomking/4734472b217779adf44c88e8da1873b9/raw/7c468c1da81d91df7b54baa1613bc5308c7ca3e9/archive_the_bk_canvas.py

2) IPython API를 이용해 notebook을 parsing해서 사용하는 방법(자세한 사용방법은 아직 확인해보지 못함)

http://ipython.readthedocs.io/en/stable/api/generated/IPython.core.getipython.html

3) nbformat과 nbconvert를 활용하는 방법(자세한 사용방법은 아직 확인해보지 못함)

https://nbconvert.readthedocs.io/en/latest/

 

## Notebook 의 Javascript 구현시 온갖 주의사항 
1) This 를 이용할 경우, js소스를 HTML로 감싸면 Window object가 가져와진다. 따라서 반드시 Javascript로 감싸야하고, 이럴 경우 편리하게 해당 cell의 output_area를 가져온다.(이는 %%javascript 셀 매직과 동일한 기능이다.)

https://stackoverflow.com/questions/39613822/how-to-select-current-cell-with-javascript-in-jupyter/50246754#50246754

2) 그런데 임의로 정의한 function안에서는 this가 또 무조건 window를 가져온다. 그래서 이럴 경우 함수의 인자를 받아서 사용해야 편하게 output_area를 가져올 수 있다.

function execute(output_area){ 
        console.log(this); // Window
        console.log(output_area); // Output_area
}

3) 그런데 문제는 setInterval 을 지정할 경우, 함수를 인자로 전달하는 방법이 따로 필요하다. 간단히 execute.bind(this, null)로 처리 가능하다. 게다가 setTimeout은 어떠한 이유인지, 실행이 되지 않아서 반드시 setInterval만 이용이 가능하다.

https://stackoverflow.com/questions/1190642/how-can-i-pass-a-parameter-to-a-settimeout-callback

4) 만약 특수한 이유로 이 Javascript객체를 사용하기 힘들다면, 다음을 읽고 output_area를 가져오는 소스를 구현해볼 수 있을 것이다.

https://github.com/ipython/ipython/blob/master/IPython/core/display.py

 

 

# Jupyter notebook python kernel 버전 바꾸기
(아래의 conda를 이용한 방법이 더 안정적이고 좋아보임)
jupyter kernelspec list 을 입력해서 현재 사용가능한 kernel 목록과 경로를 확인

cd /usr/local/share/jupyter/kernels/python3 을 입력해서 해당 경로로 들어간다

그다음 kernel.json 파일을 수정해서 우리가 원하는 python 을 실행하도록 argv의 첫 번째 값을 수정해주어야한다.

wihch python3.6 를 입력해서 파이썬의 경로를 확인하고
sudo vim kernel.json  을 입력해서 위에서 찾은 경로를 argv부분에 넣는다.

"argv": [
  "경로",
  "-m",
  "ipykernel_launcher",
  "-f",
  "{connection_file}"
 ],
 "language": "python",
 "display_name": "Python 3"

 

# 또는 아래와 같은 방식으로도 kernel list에 새로운 환경을 설정할 수 있는 것 같다.

jupyter kernelspec install python3
jupyter kernelspec uninstall python3
jupyter kernelspec remove python3

 

- 참고
https://stackoverflow.com/questions/28831854/how-do-i-add-python3-kernel-to-jupyter-ipython
https://stackoverflow.com/questions/30492623/using-both-python-2-x-and-python-3-x-in-ipython-notebook

# Conda 로 생성한 env를 jupyter에서 kernel로 만들어 실행하기

1. conda로 my_env를 만들고, 원하는 패키지를 설치한다.
   ex) conda create --name "my_env" python=3.7 -y
       conda install -n "my_env" pyhive
2. conda activate "my_env"    // conda env list로 확인 가능
3. conda install ipykernel
4. python -m ipykernel install --user --name "my_env" --display-name "Python (my_env)"

(이미 만든 kernel을 지우려면, jupyter kernelspec remove myenv )
5. jupyter notebook을 새로고침하고 new버튼을 클릭하면 새로운 kernel이 생성되어있다.
6. 기존에 띄운 노트북은 kernel 변경 후, restart를 해주어야한다.

https://stackoverflow.com/questions/39604271/conda-environments-not-showing-up-in-jupyter-notebook

 

=> 이렇게 해도 안되면, 그냥 docker로 이미지 새로 받아서 진행하는게 낫다..

 

 

# Shortcut 수동 설정하기(Edit Keyboard Shortcut이 동작하지 않을 때)

conda install -c conda-forge jupyter_contrib_nbextensions

을 설치한다음, 

~/.jupyter/nbconfig/notebook.json

에 다음을 추가한다.

{
  "keys": {
    "command": {
      "bind": {
        "ctrl-e": "jupyter-notebook:clear-cell-output"
      }
    }
  },

 
}

 

 

# Trouble Shooting

Kernel connecting에서 넘어가지 않을 때

tornado 버전을 6.대에서 낮춘다.
 
pip uninstall tornado
pip install tornado==4.5.3
 

https://stackoverflow.com/questions/54955563/jupyter-notebook-cannot-connect-to-kernel

댓글