Как я могу импортировать один блокнот Jupyter в другой - PullRequest
0 голосов
/ 17 мая 2018

Очевидно, можно импортировать один блокнот Jupyter в другой. На связанной странице есть немного кода, чтобы сделать это. Я должен добавить этот код в записную книжку? На странице не ясно об этом. Предполагается, что это общее решение, поэтому нет смысла добавлять весь этот код во все записные книжки, которые импортируют другие записные книжки. Любая помощь будет оценена. Благодарю.

1 Ответ

0 голосов
/ 17 мая 2018

Да, вы можете добавить весь этот код в блокнот, если хотите.

И да, вы не должны делать это как общее решение.

Записная книжка представляет собой сложную структуру, о которой говорится в деталях текста (я думаю, что это JSON). Он может содержать код Python, он может содержать магию - cython, bash, latex и другие, - которые не будут поняты ядром Python. По сути, вам приходится копировать часть функциональности обычного процесса импорта Python, так как изначально Python не поймет, что внутри ноутбука Ipython есть код Python.

Однако ... обычно, если у вас есть значительное количество кода Python, вы бы разбили его на модули, а затем импортировали модули. Они работают как обычно, потому что это обычный импорт Python.

Например, как только код загружен, чтобы сказать ему, как понять, что такое ноутбук, фактический импорт составляет всего

import nbpackage.mynotebook

Мы можем использовать ту же технику с кодом импорта модуля - find_notebook и NotebookLoader можно поместить в вспомогательный модуль (например, helper.py), и все, что вам нужно сделать, это из вашего ноутбука, используйте from helper import NotebookFinder.

Я подозреваю, что вам все равно придется звонить sys.meta_path.append(NotebookFinder()) из вашего ноутбука вместе с импортом.

Вот конкретный пример того, как вы можете использовать возможности импорта для создания API, созданного из блокнота:

Создать блокнот. Мы назовем это scanner.ipynb:

import os, sys
def scanner(start):
    for root, dirs,files in os.walk(start):
        # remove any already processed file
        if 'done' in dirs:
            dirs.remove('done')
        for names in files:
            name, ext = os.path.splitext(names)
            # only interested in media files
            if ext == '.mp4' or ext == '.mkv':
                print(name)

Создайте обычный файл Python с именем reuse.py. Это ваш общий многократно используемый модуль импорта Ipython :

#! /usr/env/bin python
# *-* coding: utf-8 *-*

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]

Создайте свой специальный файл API, который соединяет загрузчик выше с записной книжкой выше. Назовите это scan_api.py:

# Note the python import here
import reuse, sys

# This is the Ipython hook
sys.meta_path.append(reuse.NotebookFinder())
import scanner
# And now we can drawn upon the code
dir_to_scan = "/username/location"
scanner.scanner(dir_to_scan)
...