Desk Clarity

Everyday document & browser help

ConfigParser Rejects a Percent Sign: Choose Literal or Interpolated Values

By ON Lab · Sources checked November 9, 2026

Decide whether percent signs are literal data or interpolation syntax. Test retrieval, not just reading the file; the failure can appear only when a value is requested.

Reproduce the boundary in a disposable example

An INI value containing a percent sign fails when retrieved or assigned.

import configparser
text = "[display]\nlabel = 75% complete\n"
config = configparser.ConfigParser()
config.read_string(text)
try:
    config.get("display", "label")
except configparser.InterpolationSyntaxError:
    pass
else:
    raise AssertionError("expected interpolation failure")
assert config.get("display", "label", raw=True) == "75% complete"
literal = configparser.ConfigParser(interpolation=None)
literal.read_string(text)
assert literal["display"]["label"] == "75% complete"
escaped = configparser.ConfigParser()
escaped.read_string("[display]\nlabel = 75%% complete\n")
assert escaped["display"]["label"] == "75% complete"
print("three retrieval contracts verified")

Read the result before changing application code

Reading succeeds in the first case, so treating this as a missing-file error sends diagnosis in the wrong direction. The raw read isolates stored text from interpolation. Keep a small copy of the failing section, with secrets removed, and compare the retrieved value byte for byte.

Choose the behavior your caller needs

Use a raw read for one literal lookup, disable interpolation for a file whose whole schema is literal, or escape percent signs when you control a file that intentionally retains basic interpolation. Disabling interpolation can leave existing placeholder references unresolved. Verify every dependent setting before changing that parser-wide choice. Do not blindly double percent signs inside values supplied by unrelated formats.

Scope and limits

This covers basic ConfigParser interpolation. ExtendedInterpolation uses a different placeholder syntax; logging formatting and URL percent encoding are separate systems.

Related: compare the adjacent data or execution boundary.

The embedded example was executed in an isolated local Python process on November 9, 2026. It is a reproducible boundary check, not a test of your full application.

Sources