A literate programming tool for Python that weaves code and documentation into scientific reports
Project description
Nhandu
Nhandu (/ɲãndu/, approximately "NYAN-doo") means "spider" in many Tupi-Guarani languages, a fitting name for a tool that weaves together code and documentation, much like Knuth's original vision of literate programming.
Literate programming for Python: Write executable documents in plain .py files.
Nhandu transforms ordinary Python files with markdown comments into beautiful, reproducible reports. It's lighter than Jupyter, simpler than Quarto, and perfectly git-friendly.
Why Nhandu?
Contemporary literate programming in Python faces a documentation dilemma:
- Jupyter notebooks are powerful but use JSON format (git diffs are messy), require a browser/server, and mix code with metadata
- Quarto is feature-rich but complex, with many configuration options and a learning curve
- Pweave has not been maintained for many years and is incompatible with currently supported Python versions.
- Traditional scripts lack integrated documentation and visualization
Nhandu offers a different solution:
- Write literate programs in normal
.pyfiles: no special format, just comments - Perfect git diffs: plain text, not JSON, no timestamps, no hashes
- No server or browser required—just run the command
- Zero configuration needed: smart defaults get you started immediately
- Python-native: designed specifically for the Python ecosystem
Quick Start
Your First Literate Program
Create a file analysis.py:
#' # My First Analysis
#'
#' This is a literate Python program. Lines starting with `#'` are markdown.
#' Everything else is regular Python code.
import numpy as np
# Generate some data
data = np.random.normal(0, 1, 1000)
#' ## Results
#'
#' Let's compute some statistics:
print(f"Mean: {data.mean():.3f}")
print(f"Std Dev: {data.std():.3f}")
#' The data looks normally distributed, as expected.
Generate Your Report
nhandu analysis.py
This creates analysis.out.md (markdown format) with your code, output, and documentation.
For HTML output:
nhandu analysis.py --format html # Creates analysis.html
Features
Smart Output Capture
Nhandu automatically captures:
- Print statements and stdout
- Matplotlib plots (no
plt.show()needed!) - also works with seaborn, pandas plots, and other matplotlib-based libraries - Expression results (like Jupyter cells)
Syntax Highlighting
Server-side syntax highlighting with 50+ themes via Pygments. Popular themes include: github-dark (default), monokai, dracula, one-dark, vs, and solarized-light.
Multiple Output Formats
Markdown output can be converted to PDF, Word, LaTeX, and more using pandoc or similar tools. Native HTML support is implemented out-of-the-box.
Configuration (Optional)
Power users can customize their reports via YAML frontmatter:
#' ---
#' title: My Scientific Report
#' output: html
#' code_theme: dracula
#' plot_dpi: 150
#' number_format: ".4f"
#' ---
#'
#' # Introduction
#' ...
The number_format option controls how float values are displayed in inline code expressions (<%= expr %>). Default is .4f (4 decimal places).
It is also possible to use a configuration file (nhandu.yaml) or CLI arguments.
How It Works
The Python Literate Format
Nhandu uses a simple convention: lines starting with #' are markdown, everything else is Python code:
#' # This is a markdown heading
#'
#' Any line starting with #' is treated as **markdown**.
#' You can use all standard markdown features.
# This is a regular Python comment
x = 42 # Regular code continues to work normally
#' Back to documentation. Variables persist across blocks:
print(f"x = {x}")
Hidden code blocks let you run setup code without cluttering your report:
#| hide
import pandas as pd
import matplotlib.pyplot as plt
# Configuration code here—runs but doesn't appear in output
#|
#' Now let's analyze our data:
# This code WILL appear in the output
data = pd.read_csv("data.csv")
Execution Model
- Shared namespace: All code blocks share the same Python environment
- Sequential execution: Blocks run in document order
- Output capture: stdout, plots, and expression results are all captured
- Rich formatting: Automatic handling of matplotlib figures, pandas DataFrames, and more
Inline Code Evaluation
You can embed Python expressions directly within markdown text using inline code syntax:
<%= expression %>- Evaluates the expression and displays the result<% statement %>- Executes code without displaying output
Example:
#' # Sales Report
#'
#' <% import datetime %>
#' Report generated on <%= datetime.date.today() %>.
total_sales = 45000
target = 50000
#' We achieved <%= total_sales %> in sales.
#' That's <%= (total_sales/target)*100 %>% of our target.
#'
#' <% status = "on track" if total_sales >= target * 0.9 else "behind" %>
#' Status: We are <%= status %>.
Inline code shares the same namespace as regular code blocks, so you can reference variables, import modules, and perform calculations seamlessly within your documentation.
Examples
Check out the docs/ directory for complete demonstrations:
- 01_hello_world.py - Basic syntax and concepts [OUTPUT]
- 02_data_analysis.py - Working with data using standard library [OUTPUT]
- 03_plotting.py - Creating visualizations with matplotlib [OUTPUT]
- 04_scientific_computation.py - Numerical computing with NumPy [OUTPUT]
- 05_advanced_report.py - Complex report with pandas and multiple visualizations [OUTPUT]
- 06_inline_code.py - Inline code evaluation with
<%= %>syntax [OUTPUT]
Installation & Usage
Install from PyPI
pip install nhandu
Install from Source
git clone https://github.com/tresoldi/nhandu.git
cd nhandu
pip install -e .
Basic Usage
nhandu document.py # Process → document.out.py (markdown)
nhandu document.py --format html # Process → document.html
nhandu document.py -o report.html # Specify output file
nhandu document.py --format md # Output as markdown (default)
nhandu document.py --code-theme monokai # Custom syntax theme
nhandu document.py --verbose # Show processing details
Jupyter Notebook Integration
Nhandu can import Jupyter notebooks (.ipynb) and export to them, bridging the gap between notebook-based and literate programming workflows:
Import from Jupyter (convert .ipynb → .py):
nhandu import-notebook notebook.ipynb -o document.py
This converts a Jupyter notebook to Nhandu's literate Python format:
- Markdown cells →
#'markdown comments - Code cells → Regular Python code
- Hidden cells (with
hidetag) →#| hideblocks - Notebook metadata → YAML frontmatter
- Outputs are discarded (can be regenerated by running the document)
Export to Jupyter (convert .py → .ipynb):
nhandu export-notebook document.py -o notebook.ipynb
This creates a Jupyter notebook from your literate Python file:
#'comments → Markdown cells- Regular code → Code cells
#| hideblocks → Code cells withhidetag- YAML frontmatter → Notebook metadata
- No outputs by default (symmetric with import; open in Jupyter to run cells)
Optional: Execute notebook after export:
nhandu export-notebook document.py -o notebook.ipynb --execute
Installation note: Jupyter conversion requires the optional jupyter dependency:
pip install nhandu[jupyter]
Round-trip compatibility: Import and export use best-effort preservation of structure and metadata. While not perfectly lossless, they maintain document integrity for practical workflows.
CLI Options
Main command (process documents):
nhandu [OPTIONS] INPUT
Options:
-o, --output PATH Output file path
--format {html,md} Output format (default: markdown)
--config PATH Configuration file (YAML)
--working-dir PATH Working directory for code execution
--code-theme THEME Syntax highlighting theme
--verbose, -v Enable verbose output
--version Show version
--help Show help message
Jupyter notebook commands:
nhandu import-notebook INPUT -o OUTPUT [OPTIONS]
Import Jupyter notebook to Nhandu format
Options:
-o, --output PATH Output Python file (required)
--verbose, -v Enable verbose output
nhandu export-notebook INPUT -o OUTPUT [OPTIONS]
Export Nhandu document to Jupyter notebook
Options:
-o, --output PATH Output notebook file (required)
--execute Execute notebook after creation
--kernel KERNEL Kernel name (default: python3)
--verbose, -v Enable verbose output
Roadmap
Current priorities for future releases:
- Native PDF output support
- Custom HTML templates (Jinja2)
- Watch mode for live development
- Rich display for more object types (NumPy arrays, scikit-learn models)
- Caching system for faster re-renders
See ROADMAP.md for detailed feature planning and issues to suggest features.
Project Information
Citation and Acknowledgements
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}
}
The earliest stages of development took place within the context of the Cultural Evolution of Texts project, with funding from the Riksbankens Jubileumsfond (grant agreement ID: MXM19-1087:1).
License
MIT License - see LICENSE file for details.
Acknowledgments
Nhandu is inspired by:
- Donald Knuth's original literate programming vision
- knitr and R Markdown's approach to reproducible research
- Jupyter's interactive computing paradigm
- Quarto's modern scientific publishing tools
- Pweave's Python implementation (though no longer maintained)
Special thanks to the scientific Python community for building the ecosystem that makes tools like this possible.
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.3.1.tar.gz.
File metadata
- Download URL: nhandu-0.3.1.tar.gz
- Upload date:
- Size: 44.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
97445ab609129e7af28a39140c4db077a891564ba75508827540ffbf81e11028
|
|
| MD5 |
989f5bf4f581360700f16d245e73eec2
|
|
| BLAKE2b-256 |
d1b006075d4eac7fd7b8d9c42ca10b4e73838c2ddd28109470da749348ac56f0
|
File details
Details for the file nhandu-0.3.1-py3-none-any.whl.
File metadata
- Download URL: nhandu-0.3.1-py3-none-any.whl
- Upload date:
- Size: 25.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4fa4cca053f6cd87a5600e8f6e1f5579d2d3aa68aea46d865bcd2f182bf3f682
|
|
| MD5 |
d7f68da401599075577268abb9590f7f
|
|
| BLAKE2b-256 |
0f92553e2106d68263558e28b33a59e5c5373a24f15e280a0efb8229aa2e0044
|