Daff: Data Diff and Patch Tables
raw JSON → 1.4.2 verified Tue May 12 auth: no python install: verified
daff (data diff) is a Python library for comparing tables, producing a summary of their differences, and applying such summaries as patch files. It is optimized for comparing tables that share a common origin, effectively tracking changes between versions of the 'same' table. The library is actively maintained with frequent updates.
pip install daff Common errors
error ModuleNotFoundError: No module named 'daff' ↓
cause The 'daff' library is not installed in the Python environment where the code is being run.
fix
Install the daff library using pip:
pip install daff error TypeError: 'int' object is not iterable ↓
cause This typically occurs when passing incorrectly structured data (e.g., a flat list of numbers instead of a list of lists/rows) to `daff.PythonTableView` or similar table construction methods, as the library expects an iterable of iterables for rows and cells.
fix
Ensure that the input data to daff's table view functions is a list of lists, where each inner list represents a row and contains cell values. Example:
data = [['header1', 'header2'], [1, 2], [3, 4]]. error FileNotFoundError: [Errno 2] No such file or directory ↓
cause When using the `daff` command-line tool or its Python functions that read from files (e.g., `daff.diff_tables_from_csv`), this error occurs if the specified input CSV or other data files do not exist at the given path.
fix
Verify that the file paths provided to the
daff command or functions are correct and that the files exist in the specified locations. Warnings
breaking The keyword `async` became a reserved keyword in Python 3.7. If you were using `async` as a variable name, function parameter, or identifier in your code that interacts with `daff`, it will now cause a `SyntaxError` in Python 3.7 and newer. ↓
fix Rename any identifiers named `async` to avoid conflict with the reserved keyword. A common convention is to use `async_` instead.
gotcha The optional `sqlite3` dependency was updated from version 3 to 4 in `daff` v1.3.37. While `sqlite3` is a built-in Python module, this update might subtly affect behavior or introduce incompatibilities if your application relies on specific, advanced features or versions of SQLite that `daff` interacts with, especially when using `--input-format sqlite`. ↓
fix If encountering unexpected behavior when diffing SQLite databases, review the changes between SQLite versions 3 and 4 or ensure your environment's SQLite library is compatible with `daff`'s expectations.
gotcha Like many Python libraries, `daff`'s API might expose functions or methods where mutable objects (e.g., lists, dictionaries) are used as default arguments. Using mutable defaults can lead to unexpected side effects across multiple function calls, as the default object is created only once when the function is defined. ↓
fix Avoid using mutable objects as default arguments in your own functions. Instead, use `None` as the default and initialize the mutable object inside the function if it's `None`. Be mindful of this pattern when extending or integrating with `daff`'s API.
Install compatibility verified last tested: 2026-05-12
python os / libc status wheel install import disk
3.10 alpine (musl) wheel - 0.04s 18.5M
3.10 alpine (musl) - - 0.04s 18.5M
3.10 slim (glibc) wheel 1.6s 0.02s 19M
3.10 slim (glibc) - - 0.03s 19M
3.11 alpine (musl) wheel - 0.09s 20.6M
3.11 alpine (musl) - - 0.10s 20.6M
3.11 slim (glibc) wheel 1.8s 0.08s 21M
3.11 slim (glibc) - - 0.08s 21M
3.12 alpine (musl) wheel - 0.07s 12.4M
3.12 alpine (musl) - - 0.08s 12.4M
3.12 slim (glibc) wheel 1.6s 0.07s 13M
3.12 slim (glibc) - - 0.08s 13M
3.13 alpine (musl) wheel - 0.07s 12.2M
3.13 alpine (musl) - - 0.08s 12.1M
3.13 slim (glibc) wheel 1.6s 0.08s 13M
3.13 slim (glibc) - - 0.12s 13M
3.9 alpine (musl) wheel - 0.03s 18.0M
3.9 alpine (musl) - - 0.04s 18.0M
3.9 slim (glibc) wheel 2.0s 0.03s 18M
3.9 slim (glibc) - - 0.04s 18M
Imports
- daff
import daff
Quickstart last tested: 2026-04-24
import daff
data1 = [
['Country', 'Capital'],
['Ireland', 'Dublin'],
['France', 'Paris'],
['Spain', 'Barcelona']
]
data2 = [
['Country', 'Code', 'Capital'],
['Ireland', 'ie', 'Dublin'],
['France', 'fr', 'Paris'],
['Spain', 'es', 'Madrid'],
['Germany', 'de', 'Berlin']
]
# Create table views for the data
table1 = daff.PythonTableView(data1)
table2 = daff.PythonTableView(data2)
# Compare tables to get alignment information
alignment = daff.Coopy.compareTables(table1, table2).align()
# Prepare an empty table to hold the diff results
data_diff = []
table_diff = daff.PythonTableView(data_diff)
flags = daff.CompareFlags()
highlighter = daff.TableDiff(alignment, flags)
highlighter.hilite(table_diff)
# Render the diff to HTML for visualization
diff_render = daff.DiffRender()
diff_render.usePrettyArrows(False) # Optional: control arrow style
diff_render.render(table_diff)
table_diff_html = diff_render.html()
print("Original Table 1:", data1)
print("Modified Table 2:", data2)
print("\nHTML Diff:\n", table_diff_html)