Skip to content

three states of python in a notebook¤

most folks are familiar with notebooks in their interactive forms. in IPython, we are working in python and __name__ == "__main__". for python programs, this condition is the last stop for our program, but in notebooks it is just the beginning. i like to thing we development programs and applications in reverse in notebooks.

with experience, it is possible to author notebooks that operate as programs/scripts. this document demonstrates some advanced usage patterns to apply to get the most out of future notebooks.

the three python compilation states of notebooks:

  • an interactive state when we are authoring notebooks.
  • a script state when a notebook is used as procedural code.
  • a module when it is imported like any python resource

we need to confer with the __name__ and __file__ properties of a module's runtime to know which state we are in.

state __name__ __file__
interactive __name__ == "__main__" "__file__" not in locals()
module __name__ != "__main__" "__file__" in locals()
script __name__ == "__main__" "__file__" in locals()

python state logic¤

the three conditions are expressed in python code below

MAIN, FILE = __name__ == "__main__", "__file__" in locals()
INTERACTIVE = MAIN and not FILE
SCRIPT = MAIN and FILE
MODULE = FILE and not MAIN

these states let us write multi purpose documents that can be used in multiple contexts and sharing the benefits of all of them.

applying the condition¤

def a_bad_ass_function(who: str = "you"):

tells you who the bad ass is.

    >>> a_bad_ass_function()
    you are bad ass.

    print(F"{who} are bad ass.")

the MAIN conditions¤

INTERACTIVE notebooks and SCRIPTs both have __name__ == "__main__"

the SCRIPT conditin¤

if SCRIPT:

we import the notebook and run the command line program.

belowis a typer application that is only executed when the notebook is used as a script

    import typer
    typer.run(a_bad_ass_function)

the INTERACTIVE condition¤

    if INTERACTIVE:

data for demonstration is computed and displayed

        !midgy 2023-01-09-notebooks-states.ipynb --help
        !midgy 2023-01-09-notebooks-states.ipynb --who "y'alls"

the MODULE condition¤

if MODULE:

we import the notebook and avoid running an command line programs. often notebooks as tests are loaded under this condition.

"<module '2023-01-09-notebooks-states' from '/home/tbone/Documents/tonyfast/tonyfast/xxiii/2023-01-09-notebooks-states.ipynb'>"
if INTERACTIVE:
    import midgy.loader
    with midgy.loader.Markdown(extensions=[".ipynb"]):
        import __notebooks_states

    display(repr(__notebooks_states))

the benefits of knowing the state¤

knowing the state or context of a notebook's execution allows us to write logic that makes notebooks a swiss army knife. some advanced patterns are include testing notebooks or writing command line scripts.

applying doctests¤

TestResults(failed=0, attempted=1)

a_bad_ass_function has a doctest in the docstring. when working interactively we might want to run these tests to verify our idea works.

if INTERACTIVE:

we only want to execute the doctests in interactive mode

    import doctest
    display(doctest.testmod())