deathbeds / importnb

notebook files as source
https://importnb.readthedocs.io/en/latest/
BSD 3-Clause "New" or "Revised" License
68 stars 5 forks source link

How to import class & definitions without running whole notebook ipynb? #115

Closed blakeex closed 2 years ago

blakeex commented 3 years ago
from importnb import Notebook
init_lib = Notebook().load('my 1st notebook.ipynb')

When I run the codes above in another notebook, the entire cells in the my 1st notebook.ipynb runs, which is not ideal.

How do I load the class definitions & method definitions without running all the cells from another notebook? Is it possible?

I am running both notebooks in Google Colab. Thanks

bollwyvl commented 3 years ago

You could try Notebook(lazy=True)... it should stop loading when it hits the desired imported name... Though things like completion, etc might cause a full import.

But typically we gate the "demo" cells with:

if __name__ == "main":
    UnwantedSideEffect()

You can hoist that check to a variable as well, so it might only by 4+len(varname) keys to type.

I guess we could consider a magic importnb.Stop exception, notebook metadata, or the like, which would work if you control both documents.

filyp commented 3 years ago

This didn't work for me, the whole notebook got executed :c Maybe the solution from ipynb could be somehow adapted? https://github.com/ipython/ipynb/blob/master/ipynb/fs/defs/__init__.py

bollwyvl commented 3 years ago

The ast manipulation sounds... interesting. Related, there's the importnb.Paramterize loader, where one could also hoist the stuff to a constant, and potentially do other things with it.

tonyfast commented 2 years ago

i don't know if i'm going to implement this feature in importnb just yet, but definitely going to consider it. it sounds cool and could alleviate some overhead in some use cases. typing up this example raised some questions about what filters should be applied to the ast nodes and what shouldn't.

for the meantime, the importnb.Notebook.visit method can be overloaded to support this feature.

import ast, importnb
you_ll_never_see = None
class ClassOnly(ast.NodeTransformer):
    def visit_Module(self, node):
        return ast.Module([
            x for x in node.body 
            # what is the right set of nodes to include
            if isinstance(x, (ast.Import, ast.ImportFrom, ast.ClassDef))]
                         , node.type_ignores)

class ClassOnlyImporter(importnb.Notebook):
    def visit(self, nodes):
        return ClassOnly().visit(nodes)

with ClassOnlyImporter():
    import issue_115 as nb
[x for x in dir(nb) if not x.startswith("_")]`
tonyfast commented 2 years ago

this feature definitely has some thorns, but its added in #127. hopefully is works for yalls