2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Google Colabで自作Notebookをモジュール化する方法

Last updated at Posted at 2023-11-10

動機

Google Colabで.pyではなくドキュメントがついた.ipynbをモジュール として使えれば、共有も楽だしドキュメントとしても優秀なのでは!という気持ちで取り組みました。
備忘録として記事にします。

やること

1. Notebookをモジュール化する"ndload.py"の作成
2. ドライブのマウント
3. 自作Notebookをimport

1. Notebookをモジュール化する"ndload.py"の作成

公式ドキュメントこちら
を参考にして、カレントディレクトリ配下にnbload.pyを作成します。

以下に示すコードはこちらの引用になります。

ndload.py
#! /usr/bin/env python3
# -*- coding: utf-8 -*-

"""
load codes of jupyter notebook(.ipynb).
http://jupyter-notebook.readthedocs.io/en/latest/examples/Notebook/Importing%20Notebooks.html
"""

import io, os, sys, types
from IPython import get_ipython
from nbformat import read
from IPython.core.interactiveshell import InteractiveShell

def find_notebook(fullname, path=None):
    """find a notebook, given its fully qualified name and an optional path
    This turns "foo.bar" into "foo/bar.ipynb"
    and tries turning "Foo_Bar" into "Foo Bar" if Foo_Bar
    does not exist.
    """
    name = fullname.rsplit('.', 1)[-1]
    if not path:
        path = ['']
    for d in path:
        nb_path = os.path.join(d, name + ".ipynb")
        if os.path.isfile(nb_path):
            return nb_path
        # let import Notebook_Name find "Notebook Name.ipynb"
        nb_path = nb_path.replace("_", " ")
        if os.path.isfile(nb_path):
            return nb_path

class NotebookLoader(object):
    """Module Loader for Jupyter Notebooks"""

    def __init__(self, path=None):
        self.shell = InteractiveShell.instance()
        self.path = path

    def load_module(self, fullname):
        """import a notebook as a module"""
        path = find_notebook(fullname, self.path)

        print("importing Jupyter notebook from %s" % path)

        # load the notebook object
        with io.open(path, 'r', encoding='utf-8') as f:
            nb = read(f, 4)

        # create the module and add it to sys.modules
        # if name in sys.modules:
        #    return sys.modules[name]
        mod = types.ModuleType(fullname)
        mod.__file__ = path
        mod.__loader__ = self
        mod.__dict__['get_ipython'] = get_ipython
        sys.modules[fullname] = mod

        # extra work to ensure that magics that would affect the user_ns
        # actually affect the notebook module's ns
        save_user_ns = self.shell.user_ns
        self.shell.user_ns = mod.__dict__

        try:
            for cell in nb.cells:
                if cell.cell_type == 'code':
                    # transform the input to executable Python
                    code = self.shell.input_transformer_manager.transform_cell(
                        cell.source)
                    # run the code in themodule
                    exec(code, mod.__dict__)
        finally:
            self.shell.user_ns = save_user_ns
        return mod

class NotebookFinder(object):
    """Module finder that locates Jupyter Notebooks"""
    def __init__(self):
        self.loaders = {}

    def find_module(self, fullname, path=None):
        nb_path = find_notebook(fullname, path)
        if not nb_path:
            return

        key = path
        if path:
            # lists aren't hashable
            key = os.path.sep.join(path)

        if key not in self.loaders:
            self.loaders[key] = NotebookLoader(path)
        return self.loaders[key]

# Register the hook, Now we register the NotebookFinder with sys.meta_path
sys.meta_path.append(NotebookFinder())
print("imported nbload.py")

2. ドライブのマウント

メインとなるNotebook(ここではmain.ipynbとします)でdriveをマウントします。
その後ディレクトリ移動とパスを通します。
your-directoryは作業ディレクトリに応じて合わせてください。
自身のフォルダを右クリックしてパスを張り付ければ良いです。

main.ipynb
from google.colab import drive
drive.mount('/content/drive')

import os
_colab_dir = "{your-directory}"
os.chdir(_colab_dir)
import sys
sys.path.append('{your-directory}')

import nbload as nb

3. 自作Notebookをimport

遂に自作Notebookをmain.ipynbでインポートして使えるようにします。
例えば、同ディレクトリ内にモジュール化したいNotebook
Hello.ipynbがあったとします。

Hello.ipynb
def say():
    print("Hello!")

このHello.ipynb内の関数say()を、main.ipynbで呼び出したい場合は、

main.ipynb
import Hello 
Hello.say()  #"Hello!"

とすることでできます!

注意!
モジュール化した.ipynbをimportする際、モジュール内の処理が全て実行されてしまいます。
そのため、import後に好きなタイミングでモジュール内の処理を実行したい場合は、処理を関数などにしておく必要があります。


このようにして、Notebookを丸ごとモジュール化して、その中の関数だけを呼び出すことができるようになりました!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?