[PYTHON] Import specific cells from other notebooks with Jupyter notebook

Introduction

When doing data analysis or experimentation with Jupyter notebook, it is often the case that you want to import a specific cell of another notebook that defines a class for analysis. Here are two ways that might work.

1. %% writefile magic command

The easiest way is to use the magic command %% writefile. The contents of the cell are copied to filename by setting %% writefile filename at the beginning of the cell. All you have to do now is import the filename from another notebook.

Cell you want to read from another notebook


%%writefile hoge.py
class Hoge:
    def __init__(self):
        print('Hello from Hoge')

Read and use the contents of other output notebook cells


import hoge

x = hoge.Hoge()

2. Do your best to make your own

Official says, "Everyone wants to do it, and they don't have to worry about it with just a public API. If you are saying "You can do it!" ~~, I want you to be able to do it with just one command ~~, so I will make it myself by referring to the linked code [^ t dual].

[^ tdual]: @tdual wrote article about the contents of the link. After investigating, the code published in @ tdual's article (that is, the officially introduced code) seems to be mixed with legacy code that has been deprecated since around Python 3.4, so modcell has made some modifications. ____ is inside. If modcell doesn't work because of version, you should try @ tdual's code.

The linked code will execute all the code cells of the notebook loaded as a module, so try modifying it so that the cell with # modcell in the comment at the beginning of the code cell is identified and loaded. It was.

Please use it if you like because it was released as a library called modcell.

(If you look for it, there should be someone who makes a library that is clever than me, so if anyone knows a good library, I would appreciate it if you could let me know.)

Usage modcell searches for files with the extension .ipynb that exist in the directory registered in sys.path, and is written in the first line (excluding magic commands) of the code cell. Identify the comment # modcell and import it as a module.

Installation

pip install modcell

import modcell

Importing the modcell module adds a loader to sys.meta_path to load the .ipynb. After that, it is possible to import files with the extension .ipynb.

import modcell as mods

Import .ipynb file

Importing with a name without the extension, just like a regular module, will import all cells with # modcell at the beginning of the cell (except for the IPython magic command).

Notebook on the imported side(test_module.ipynb)A certain cell


# modcell
class TestModule:
    def __init__(self):
        pass

    def hello(self):
        print('Hello from TestModule')

A certain cell in the notebook on the importing side


import test_module as mod

x = mod.TestModule()
x.hello()

modcell ignores IPython magic commands (lines starting with! Or% ). That is, % autoreload and %% time are not executed when importing by modcell.

Also, I don't know if modcell itself supports% autoreload because I haven't tested it. We have confirmed that if you do Restart and Run all, other notebooks will be reloaded.

compile

Upward compatible with %% writefile. Outputs all imported cells to a file.

import modcell as mods
import test_module

with open('module.py', mode='w') as f:
    mods.compile(out=f, source_info=True)

It is formatted as follows.

module.py


# test_module.ipynb ---------
# ---

class TestModule:
    def __init__(self):
        pass
    
    def hello(self):
        print('Hello from TestModule')

# ---
# --------- test_module.ipynb

The delimited comment corresponding to the cell is output from the viewpoint of debugging etc., but if it is in the way, it will not be output if source_info = False is specified.

Import only cells with specific tags from .ipynb

Write a comment at the beginning of the cell

test_module.A certain cell of ipynb


# modcell: tagname
class TestModule:
    def __init__(self):
        pass

    def hello(self):
        print('Hello from TestModule')

You can add only one tag to each cell by using the syntax of. When importing

import modcell as mods

mod = mods._import('test_module', tag='tagname')

x = mod.TestModule().hello()

By doing so, only cells with the tag tagname can be read.

Compile to multiple module files

By default, modcell creates one instance of the modcell.ModCell class, and all functions are executed as methods of that default instance. This default instance can be obtained with the modcell.default () function, but it is deprecated by the user.

Users can create multiple ModCell instances as needed.

import modcell as mods

mod_1 = mods.ModCell()
mod_2 = mods.ModCell()
...

In other words, you can generate multiple .py files from multiple .ipynb by executing the following code.

import modcell as mods

mod_debug = mods.ModCell()
nb1_debug = mod_debug._import('notebook_1', tag='debug')
nb2 = mod_debug._import('notebook_2')
nb3 = mod_debug._import('notebook_3')
with open('../module/mod_debug.py', mode='w') as f:
    mod_debug.compile(out=f)

mod_test = mods.ModCell()
nb1_test = mod_test._import('notebook_1', tag='test')
nb4 = mod_test._import('notebook_4')
with open('../module/mod_test.py', mode='w') as f:
    mod_test.compile(out=f)

bonus

Another way I came up with was to "attach to the IPython kernel and pull the contents of the code cells of other notebooks", but it seems that the contents of the code cells are retained by the front-end JavaScript. However, the IPython kernel seems to hold only the code after the parser is applied, so it was a bad idea.

https://stackoverflow.com/questions/51121647/get-the-current-contents-of-the-entire-jupyter-notebook

Recommended Posts

Import specific cells from other notebooks with Jupyter notebook
Using Graphviz with Jupyter Notebook
Use pip with Jupyter Notebook
Use Cython with Jupyter Notebook
Play with Jupyter Notebook (IPython Notebook)
Server management with Jupyter (1) import
Allow external connections with jupyter notebook
Formatting with autopep8 on Jupyter notebook
Visualize decision trees with jupyter notebook
Make a sound with Jupyter notebook
Use markdown with jupyter notebook (with shortcut)
Add more kernels with Jupyter Notebook
Convenient analysis with Pandas + Jupyter notebook
Settings when reading S3 files with pandas from Jupyter Notebook on AWS
Use nb extensions with Anaconda's Jupyter notebook
Use apache Spark with jupyter notebook (IPython notebook)
I want to blog with Jupyter Notebook
Use Jupyter Lab and Jupyter Notebook with EC2
Try SVM with scikit-learn on Jupyter Notebook
Use BigQuery from your local Jupyter Notebook
To import your own module with jupyter
How to use jupyter notebook with ABCI
Linking python and JavaScript with jupyter notebook
[Jupyter Notebook memo] Display kanji with matplotlib
Rich cell output with Jupyter Notebook (IPython)
Use jupyter notebook by connecting from another host
How to debug with Jupyter or iPython Notebook
When Html cannot be output with Jupyter Notebook
Analytical environment construction with Docker (jupyter notebook + PostgreSQL)
Data analysis for improving POG 2 ~ Analysis with jupyter notebook ~
Enable Jupyter Notebook with conda on remote server
Easily convert Jupyter Notebooks to blogs with fastpages
Try using conda virtual environment with Jupyter Notebook
Fill the browser with the width of Jupyter Notebook
Bulk download images from specific URLs with python
Graph drawing with jupyter (ipython notebook) + matplotlib + vagrant