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.
%reload_ext pidgy
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()` |
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.
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.")
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 `SCRIPT`s both have `__name__ == "__main__"`
the MAIN
conditions¤
INTERACTIVE
notebooks and SCRIPT
s 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 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.
if MODULE:
we import the notebook and avoid running an command line programs. often notebooks as tests are loaded under this condition.
if INTERACTIVE:
import midgy.loader
with midgy.loader.Markdown(extensions=[".ipynb"]):
import __notebooks_states
display(repr(__notebooks_states))
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].
[testing notebooks]: https://nbviewer.org/gist/tonyfast/b617e4f87337a50e1361ab043b53c2c7
[writing command line scripts]: https://tonyfast.github.io/tonyfast/xxii/2022-12-19-integrating-typer.html
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 `doctest`s
applying doctest
s¤
`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 `doctest`s in interactive mode
import doctest
display(doctest.testmod())
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 doctest
s in interactive mode
import doctest
display(doctest.testmod())