mwouts / jupytext

Jupyter Notebooks as Markdown Documents, Julia, Python or R scripts
https://jupytext.readthedocs.io
MIT License
6.64k stars 386 forks source link

Make generated .py files importable #592

Open kenjioman opened 4 years ago

kenjioman commented 4 years ago

Sorry in advance if this feature already exists and I just don't know about it, or if there are easy work-arounds to get the same behavior.

Taking a look at the generated python files in the demo, it looks like everything in the notebooks are kept at global scope in the python file. So, if these were to be imported by any other files, everything would be run on import.

Instead, it would be nice if generated python files (or, at least one variant of them) followed this structure:

"""any imports needed
import sys, os, pandas as pd, etc
"""

"""function/ class definitions in the notebook
def sum(x, y):
    return x + y
etc
"""

def main():
    """code from most of the cells with functions/ classes defined above
       called/ instantiated at the appropriate place
       a = 1
       b = 2
       z = sum(a, b)
       # Wow, look at that sum!
       etc
    """

if __name__ == '__main__':
    main()

Doing this would:

  1. Allow these scripts to be imported by other python programs with only desired functionality being run (if someone wants to import and run everything, they could just do import genrated_script and generated_script.main().
  2. Make these scripts easily testable (by importing them into a test framework and testing what functions/classes you want.
mwouts commented 4 years ago

Hello @kenjioman , this is a great question!

We say a word about that at https://jupytext.readthedocs.io/en/latest/examples.html#importing-jupyter-notebooks-as-modules. Currently the paragraph is very short and I'll be happy to improve it based on your feedback.

So, you have the option to 'tag' your code cells with active-ipynb if you want them to be active only in Jupyter, and tag raw cells with active-py if you want them to be active only in the script.

Now, if you're open to changing the notebook itself and to only write functions, then I suppose you could code it as in your example, and finish with a code cell with a tag active-ipynb that simply calls main() - what do you think?

Skylion007 commented 4 years ago

@kenjioman I actually have a hack does make them portable and testable! In two different ways:

@mwouts Maybe we could merge this testing hack in JuPyText as a utility?

This notebook will run as an iPython notebook while still being importable. https://github.com/facebookresearch/habitat-sim/blob/master/examples/tutorials/nb_python/rigid_object_tutorial.py

Now if you want to run the entire file as a function, I actually do that in our testing suite: https://github.com/facebookresearch/habitat-sim/blob/master/tests/test_examples.py