docling-project / docling-project/docling
Feature request: public API to release ConversionResult backend after convert() returns
- Dominant language
- Python
- Stars
- 66.4k
- Forks
- 4.8k
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 95
Description
### Problem
After `DocumentConverter.convert(...)` returns, the parsing backend (PyMuPDF for PDF, docling-parse for some image formats) reachable at `ConversionResult.input._backend` continues to hold OS-level file handles and memory-mapped regions until the `ConversionResult` is garbage-collected.
On long-running batch conversions this causes:
- Open file-descriptor accumulation. On macOS the default per-process soft limit is 256 (`ulimit -n`), which is reachable on PDF batches in the 200+ file range before GC pressure resolves it.
- Resident-memory growth from `mmap` regions the OS does not reclaim until the holding Python object is collected.
- Slow tear-down at end-of-batch because GC settles asynchronously on the conversion thread.
The `DoclingDocument` is fully built by the time `convert()` returns — the backend is no longer producing pages — so releasing it immediately is safe.
### Current workaround
```python
backend = conv_res.input._backend # private attribute
if backend is not None:
backend.unload()
```
This reaches into `InputDocument._backend`, which is private; the leading underscore signals the attribute can be renamed or restructured at any minor release.
Verified against `docling==2.95.0`, `docling-core==2.77.0` (via `dir(InputDocument)` / `dir(ConversionResult)`): neither class exposes any `unload` / `release` / `close` / `cleanup` / `discard` method. Only `ConversionResult.load` exists (the opposite direction). `InputDocument._backend` is the only access point to the backend instance.
### Proposed API shapes (any one would resolve)
**1. Method on `ConversionResult`:**
```python
conv_res = converter.convert(source)
# ... process conv_res.document ...
conv_res.release() # or conv_res.unload_input()
```
**2. Context-manager shape:**
```python
with converter.convert(source) as conv_res:
# ... process conv_res.document ...
# backend released on __exit__
```
**3. Method on `InputDocument`:**
```python
conv_res.input.release()
```
Any of these would let downstream batch consumers free backend resources promptly without touching private attributes.
### Context
This is a feature request, not a bug. The implementation is small — one method delegating to the existing backend `.unload()`. Happy to open a PR if a preferred shape is indicated.
Contributor guide
Research direction
Start at DocumentConverter.convert() and the ConversionResult and InputDocument entry points, then trace how InputDocument._backend is created and how its existing unload() is used. Select one public release shape, cover backend cleanup after conversion including the no-backend case, and verify that the completed document remains usable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100