A literate programming tool for Python that weaves code and documentation into scientific reports
Project description
Nhandu
Literate programming for Python: write executable documents in plain .py files.
Nhandu transforms Python files with markdown comments into beautiful, reproducible reports. It is lighter than Jupyter, simpler than Quarto, and perfectly git-friendly.
Nhandu (/ɲãndu/, approximately "NYAN-doo") means "spider" in many Tupi-Guarani languages, reflecting its role in weaving code and documentation together, much like Knuth's original vision of literate programming.
Installation
pip install nhandu
For Jupyter notebook conversion support:
pip install nhandu[jupyter]
Requirements: Python 3.10 or later.
Quick Start
Create a file called analysis.py:
#' # My First Analysis
#'
#' Lines starting with `#'` are markdown.
#' Everything else is regular Python code.
import math
#' ## Results
print(f"Pi is approximately {math.pi:.4f}")
print(f"Euler's number is approximately {math.e:.4f}")
#' Variables persist between code blocks:
radius = 5
area = math.pi * radius ** 2
print(f"Area of circle with radius {radius}: {area:.2f}")
Generate a report:
nhandu analysis.py # Markdown output → analysis.out.md
nhandu analysis.py --format html # HTML output → analysis.html
Why Nhandu?
Python's literate programming tools each come with trade-offs:
- Jupyter notebooks use JSON (messy git diffs), require a browser, and mix code with metadata
- Quarto is powerful but complex, with a steep learning curve
- Pweave is no longer maintained and incompatible with current Python versions
Nhandu offers a different approach:
| Jupyter | Quarto | Nhandu | |
|---|---|---|---|
| File format | JSON (.ipynb) |
Markdown (.qmd) |
Python (.py) |
| Git diffs | Noisy | Clean | Clean |
| Requires browser/server | Yes | No | No |
| Configuration needed | Kernels, metadata | YAML headers, engines | Nothing |
| Editor support | Specialized | Any + plugins | Any Python editor |
| Learning curve | Medium | High | Minimal |
Features
Smart Output Capture
Nhandu automatically captures:
- Print statements and stdout
- Matplotlib figures (no
plt.show()needed) — also works with seaborn, pandas.plot(), and other matplotlib-based libraries - Expression results (last expression in a block is displayed, like Jupyter)
Syntax Highlighting
Server-side syntax highlighting via Pygments with 49 built-in themes. Popular themes include github-dark (default), monokai, dracula, one-dark, and solarized-light.
List all available themes:
nhandu --list-themes
HTML Templates
Three built-in templates for HTML output:
default— clean sans-serif layoutacademic— serif, paper-like styling for research reportscorporate— blue accents, professional look
Select via --template academic or template: frontmatter. Add custom CSS overrides with --template-css custom.css. List available templates:
nhandu --list-templates
Templates are orthogonal to --code-theme (Pygments syntax highlighting).
Output Formats
- Markdown (default) — convertible to PDF, Word, or LaTeX via pandoc
- HTML — self-contained files with embedded plots, syntax highlighting, and responsive styling
Inline Code
Embed Python expressions directly in markdown text:
total = 1500
target = 2000
#' We achieved <%= total %> in sales,
#' which is <%= (total/target)*100 %>% of our target.
<%= expression %>— evaluate and display the result<% statement %>— execute without output
Inline code shares the same namespace as regular code blocks.
Hidden Code Blocks
Run setup code without cluttering the report:
#| hide
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('seaborn-v0_8')
#|
#' Now the analysis begins:
data = pd.read_csv("data.csv")
YAML Frontmatter
Configure reports via optional frontmatter:
#' ---
#' title: My Scientific Report
#' output: html
#' code_theme: dracula
#' template: academic
#' plot_dpi: 150
#' number_format: ".2f"
#' show_footer: false
#' ---
| Option | Default | Description |
|---|---|---|
title |
filename | Document title (used in HTML <title>) |
output |
markdown |
Output format: markdown or html |
code_theme |
github-dark |
Pygments syntax highlighting theme |
plot_dpi |
100 |
DPI for saved matplotlib figures |
number_format |
.4f |
Python format spec for inline float values |
template |
default |
HTML template: default, academic, or corporate |
template_css |
(none) | Path to custom CSS file appended to template styles |
show_footer |
true |
Show "Made with Nhandu" footer in HTML |
working_dir |
(current) | Working directory for code execution |
Configuration can also be provided via a YAML file (--config config.yaml) or CLI arguments.
CLI Reference
Processing Documents
nhandu INPUT [OPTIONS]
# Examples:
nhandu analysis.py # → analysis.out.md (markdown)
nhandu analysis.py --format html # → analysis.html
nhandu analysis.py -o report.html # Specify output path
nhandu analysis.py --code-theme monokai # Custom syntax theme
nhandu analysis.py --no-footer # Disable HTML footer
nhandu analysis.py -v # Verbose with progress
nhandu analysis.py --parse-only # Show structure, skip execution
Options
positional:
INPUT Input file (.py literate Python)
options:
-o, --output PATH Output file path
--format {html,md,markdown} Output format (default: markdown)
--config PATH Configuration file (YAML)
--working-dir PATH Working directory for code execution
--code-theme THEME Syntax highlighting theme
--template TEMPLATE HTML template (default, academic, corporate)
--template-css PATH Custom CSS file to append to template styles
--no-footer Disable footer in HTML output
--parse-only Parse and show structure without executing
-v, --verbose Verbose output with progress
--list-themes List all available syntax themes
--list-templates List all available HTML templates
--version Show version and exit
Jupyter Notebook Conversion
Import from Jupyter:
nhandu import-notebook notebook.ipynb -o document.py
Export to Jupyter:
nhandu export-notebook document.py -o notebook.ipynb
nhandu export-notebook document.py -o notebook.ipynb --execute # With outputs
Conversion preserves markdown cells, code cells, hidden cell tags, and metadata. Requires pip install nhandu[jupyter].
The Literate Python Format
The format is simple: lines starting with #' are markdown, everything else is Python code.
#' # Heading
#'
#' Markdown text with **bold**, *italic*, `code`,
#' [links](https://example.com), and tables.
# This is a regular Python comment (stays in the code block)
x = 42
#' Back to documentation. The variable `x` is still in scope:
print(f"x = {x}") # Output captured automatically
Execution Model
- Shared namespace — all code blocks share the same Python environment
- Sequential execution — blocks run top to bottom, in document order
- Automatic capture — stdout, expression results, and matplotlib figures are captured without any special syntax
Python API
Nhandu can also be used as a library:
from nhandu import parse, execute, render
content = open("document.py").read()
doc = parse(content, source_path="document.py")
executed = execute(doc)
html = render(executed, format="html")
Progress tracking is available via callback:
def on_progress(index, total, block):
print(f"Block {index}/{total}: {'ERROR' if block.error else 'OK'}")
executed = execute(doc, on_progress=on_progress)
Available themes can be listed programmatically:
from nhandu.renderer import list_themes
print(list_themes())
Examples
The docs/ directory contains complete demonstrations:
| Example | Description | Output |
|---|---|---|
| 01_hello_world.py | Basic syntax and concepts | HTML |
| 02_data_analysis.py | Data analysis with the standard library | HTML |
| 03_plotting.py | Matplotlib visualizations | HTML |
| 04_scientific_computation.py | NumPy numerical computing | HTML |
| 05_advanced_report.py | Pandas and multiple visualizations | HTML |
| 06_inline_code.py | Inline code evaluation | HTML |
Project Information
Citation
If you use Nhandu in your research, please cite:
@software{tresoldi2025nhandu,
author = {Tresoldi, Tiago},
title = {Nhandu: Literate Programming for Python},
year = {2025},
publisher = {Department of Linguistics and Philology, Uppsala University},
address = {Uppsala, Sweden},
url = {https://github.com/tresoldi/nhandu},
orcid = {0000-0002-2863-1467}
}
Acknowledgments
Nhandu is inspired by Donald Knuth's literate programming vision, knitr and R Markdown's approach to reproducible research, Jupyter's interactive computing paradigm, Quarto's scientific publishing tools, and Pweave's Python implementation.
The earliest stages of development took place within the Cultural Evolution of Texts project, with funding from the Riksbankens Jubileumsfond (grant agreement ID: MXM19-1087:1).
License
MIT License. See LICENSE for details.
Links
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nhandu-0.4.0.tar.gz.
File metadata
- Download URL: nhandu-0.4.0.tar.gz
- Upload date:
- Size: 48.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1f52c881a2d1dd0244f35d8c9d9b4529a1148735d97d6c26adab27dcd3d2e66
|
|
| MD5 |
f8cb50f23ec5934da23b69a29ab96d7a
|
|
| BLAKE2b-256 |
23d68aa83f705a88a5f141d9bbb316d72e9d03ac0c6462e0f0e885d6c8c333f1
|
File details
Details for the file nhandu-0.4.0-py3-none-any.whl.
File metadata
- Download URL: nhandu-0.4.0-py3-none-any.whl
- Upload date:
- Size: 30.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33e86333bfdea183b681383c657a71e5bde28727cc59dbc44fc2b811628f537d
|
|
| MD5 |
b51c347dabb9c70e20bf1e6e66320db6
|
|
| BLAKE2b-256 |
a385c66f59532a34862bcd448ddbcfbd9a1294969707f7e6d2fb088ba93f2f9a
|