ipynb_importer.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import io, os,sys,types
  2. from IPython import get_ipython
  3. from nbformat import read
  4. from IPython.core.interactiveshell import InteractiveShell
  5. class NotebookFinder(object):
  6. """Module finder that locates Jupyter Notebooks"""
  7. def __init__(self):
  8. self.loaders = {}
  9. def find_module(self, fullname, path=None):
  10. nb_path = find_notebook(fullname, path)
  11. if not nb_path:
  12. return
  13. key = path
  14. if path:
  15. # lists aren't hashable
  16. key = os.path.sep.join(path)
  17. if key not in self.loaders:
  18. self.loaders[key] = NotebookLoader(path)
  19. return self.loaders[key]
  20. def find_notebook(fullname, path=None):
  21. """find a notebook, given its fully qualified name and an optional path
  22. This turns "foo.bar" into "foo/bar.ipynb"
  23. and tries turning "Foo_Bar" into "Foo Bar" if Foo_Bar
  24. does not exist.
  25. """
  26. name = fullname.rsplit('.', 1)[-1]
  27. if not path:
  28. path = ['']
  29. for d in path:
  30. nb_path = os.path.join(d, name + ".ipynb")
  31. if os.path.isfile(nb_path):
  32. return nb_path
  33. # let import Notebook_Name find "Notebook Name.ipynb"
  34. nb_path = nb_path.replace("_", " ")
  35. if os.path.isfile(nb_path):
  36. return nb_path
  37. class NotebookLoader(object):
  38. """Module Loader for Jupyter Notebooks"""
  39. def __init__(self, path=None):
  40. self.shell = InteractiveShell.instance()
  41. self.path = path
  42. def load_module(self, fullname):
  43. """import a notebook as a module"""
  44. path = find_notebook(fullname, self.path)
  45. print ("importing Jupyter notebook from %s" % path)
  46. # load the notebook object
  47. with io.open(path, 'r', encoding='utf-8') as f:
  48. nb = read(f, 4)
  49. # create the module and add it to sys.modules
  50. # if name in sys.modules:
  51. # return sys.modules[name]
  52. mod = types.ModuleType(fullname)
  53. mod.__file__ = path
  54. mod.__loader__ = self
  55. mod.__dict__['get_ipython'] = get_ipython
  56. sys.modules[fullname] = mod
  57. # extra work to ensure that magics that would affect the user_ns
  58. # actually affect the notebook module's ns
  59. save_user_ns = self.shell.user_ns
  60. self.shell.user_ns = mod.__dict__
  61. try:
  62. for cell in nb.cells:
  63. if cell.cell_type == 'code':
  64. # transform the input to executable Python
  65. code = self.shell.input_transformer_manager.transform_cell(cell.source)
  66. # run the code in themodule
  67. exec(code, mod.__dict__)
  68. finally:
  69. self.shell.user_ns = save_user_ns
  70. return mod
  71. sys.meta_path.append(NotebookFinder())