มีโค้ดที่เขียนไว้บน Jupyter notebook แล้วอยากเอามันมาส่งค่ากลับ แบบ JSON เรียกผ่าน Ajax ได้ คนขี้เกียจแบบผม ต้องเอา Jupyter ตอบ JSON กลับไปเลยซิ ด้วยความที่ ไม่ได้เชี่ยวชาญการใช้ Jupyter ก็เลยค้นๆไป เจอวิธี และใช้ได้ มาเล่าสู่กันอ่าน
ผมรู้จัก IPython มาเมื่อนานมาแล้ว นานมาก เกิน 5 ปี ตอนนั้นลองใช้เฉยๆ ยังหนุ่ม ยังแน่นลองไปเรื่อย ตอนกระโน้นเขียน Python ได้นิดหน่อย ใช้ print, for, if
ได้ พอลองใช้ IPython ดูแล้วก็งงๆ ใช้ทำไมว่ะ แค่เปิดหน้าเว็บ และรันโค้ดได้ ไม่เห็นมีประโยชน์ เลยไม่ได้เล่นต่อเลย
ผ่านมาจากตอนนั้นก็นาน ผมเห็นโปรเจคหนึ่งชื่อ iTorch มันคือ IPython kernel ที่เขียนภาษา Lua ได้ เหมือนกับที่ เขียน Python บน IPython เลยซึ่ง มันต้องติดตั้ง IPython ก่อน แต่ติดตั้งไปมาตอนสั่ง pip install ipython
ผมเจอคำเตือน และให้ใช้ Jupyter แทน ค้นๆไปมา เอ้อ มันดีเว้ย มันคือ IPython นั่นแหละ ก็เลยได้ลองใช้มาเรื่อยๆ แต่ไม่ได้จริงจังมาก
ช่วงสอง สามเดือนที่ผ่านมา มีงานที่ใช้ Python ทำการจัดการข้อมูลค่อนข้างเยอะ แรกๆเขียน Python script บน server เลย ssh ไปทำงาน พอใช้ๆไป ความต้องการเริ่มมาก เลยกลับมาหาเพื่อนเก่า IPython/Jupyter เพื่อความสะดวกในการจัดการข้อมูลที่เริ่มเยอะและซับซ้อนมากขึ้น
รูปจาก http://jupyter.org/
Jupyter เอง มันติดตั้งไม่ยาก ถ้าใครเคยใช้ Python ก็พอจะรู้จาก pip
สั่งติดตั้งผ่าน pip install jupyter
ได้เลย จบ แต่นี่มันปี 2017 แล้ว ใครๆก็ใช้ Docker ทำไมเราจะต้องใช้ pip
vbvb ถ้าใครขี้เกียจติดตั้ง Docker และรัน Jupyter ก็ใช้ตามนี้ครับ
จากนั้นหน้าเว็บก็จะเปิดขึ้นมา
ใส่ token ที่ได้ตอนรันคำสั่ง เพื่อทำการ login หลังจาก login เสร็จจะเจอไฟล์ต่างๆที่ไดเรคทอรี่ ที่เรารันคำสั่งขึ้นมา
ลองสร้าง Notebook ขึ้นมา เลือกเป็น Python แล้วกัน
จะได้หน้าตามาประมาณนี้ แต่โล่งๆ ไม่มีโค้ดอะไร ลองใส่โค้ด และรันดูได้เลย
อันข้างบนๆคือเขียนโค้ดบน Jupyter แบบง่ายๆ เหมือนเขียน Python ปกติ แต่ทำผ่านหน้าเว็บ อาจจะยังไม่ตื่นเต้นอะไรก็ได้ รูปข้างล่างนี่ คือผมลองเอา Jupyter รันบนเครื่องตัวเอง แล้วใช้ PyMongo ซึ่งเป็น MongoDB Driver สำหรับ Python เรียกไปยัง MongoDB server ที่อยู่ในวง VPN เพื่อเอาค่ามาลองวาดกราฟดู โดยเรียกใช้ Matplotlib ได้เลย จริงๆแล้ว มันทำเป็น Inline ได้ ลืมแคปรูปไว้ และหาไฟล์ notebook ไม่เจอ
การจัดการข้อมูลเยอะๆ ใช้เครื่องคอมพับแค่เปิดไฟล์ ยังต้องรอนานเลย มันจึงเป็นเหตุผลว่า ทำไมจะต้องเอา Jupyter ไปรันบนเครื่อง Server แรงส์ๆ
ไหนละ REST API ไม่เห็นมีเลย ถถถถ
ได้เวลาแล้วๆ ตัว REST API นี่ จะใช้ Docker ร่วมด้วยน่ะ เพราะว่า อยากรันให้มันอยู่ใน Container มากกว่า จะทำให้เครื่องโฮสต์ต้องติดตั้งอะไรต่อมิอะไรเพิ่มข้างนอก เดี๋ยวมันรก ถ้าใช้ Docker ตอนไหนไม่ใช้ Jupyter แล้ว ก็ลบมันทิ้งไปเลย
เริ่ม!
ผมจะมโนไปเองว่า คนอ่านมี Docker ติดตั้งอยู่แล้ว บนเครื่องที่เป็น Linux โดยผมจะสร้างไดเรคทอรี่มาแบบนี้
jupyter
└── work
แล้วก็รัน Docker Jupyter base notebook ด้วยคำสั่งนี้
ต้อง chown 1000 work
ก่อน เพื่อให้ Jupyter เขียนไฟล์ลง work ได้ หลังจากที่รันเสร็จแล้ว จะดู token ได้จากคำสั่ง
...
Copy/paste this URL into your browser when you connect for the first time,
to login with a token:
http://localhost:8888/?token=4b1240ef5ae45d4b22a5338a9aec66144a2757bf5f3ce390
หลังจาก login เสร็จแล้ว สร้าง Notebook ชื่อ api ในไดเรคทอรี่ชื่อ work และลองรันดู แบบนี้
ตรวจสอบดูไฟล์ใน work จะได้ไฟล์ชื่อ api.ipynb
work
└── api.ipynb
ต่อไปมาสร้าง REST API ง่ายๆด้วย Jupyter Kernel Gateway สร้างไฟล์ชื่อ Dockerfile
FROM jupyter/base-notebook
MAINTAINER Narate Ketram <rate\[\@\]dome.cloud>
RUN pip install jupyter_kernel_gateway
ENTRYPOINT ["tini", "--", "jupyter", "kernelgateway", "--KernelGatewayApp.api=notebook-http", "--KernelGatewayApp.ip=0.0.0.0"]
COPY work/api.ipynb /srv/
CMD ["--KernelGatewayApp.seed_uri=/srv/api.ipynb"]
เสร็จแล้วสั่ง build docker image
และสั่งรัน docker container
ช้าก่อน เรายังไม่ได้บอก Notebook ว่าให้รับ Request มาที่ URI ไหน ให้แก้ api notebook ใส่ Annotations ให้มันที่บรรทัดแรก แบบนี้
จากนั้นรัน docker container ใหม่ ลบของเก่าทิ้งก่อน
รันใหม่ โดยการ map ไฟล์ api.ipynb เข้าไป
จากนั้นทดสอบเรียก API ด้วย curl
In [99] : print('จบ')
จบ
ที่มาของทั้งหมดนี้ อ่านมาจากที่นี่ และปรับใช้ http://blog.ibmjstart.net/2016/01/28/jupyter-notebooks-as-restful-microservices/