ascii()

The ASCII-safe cousin of repr() — same format, but non-ASCII becomes escape sequences.

Built-in functionPython 3.0+Live demo
Common call
log.debug("got %s", ascii(value))
Returns
a str containing only ASCII characters
Replaces
repr() when the output must fit an ASCII-only environment
Watch out
the output is pure ASCII but often LESS READABLE than repr(); use repr in modern UTF-8 environments
ascii(objectobjectAny value. Python calls repr() on it, then escapes every non-ASCII codepoint.type: Any · required)
str

Demo

Live evaluation
Try:
Inputs
xstrany value
Output
ascii('hello')
'\'hello\''

ascii() is repr() with a filter: every character with codepoint >= 128 becomes an escape sequence (\xHH, \uXXXX, or \UXXXXXXXX). This produces output that is safe for ASCII-only sinks — old log formats, some file systems, protocols that mangle non-ASCII. In modern UTF-8 environments repr() is usually more readable.

Parameters

NameTypeRequiredDescription
objectAnyyesAny value. Python calls repr() on it, then escapes every non-ASCII codepoint.

Return value

strA string like repr(object), but every character outside the ASCII range (codepoint >= 128) is replaced with an escape sequence: \xHH for U+0080..U+00FF, \uXXXX for U+0100..U+FFFF, \U00XXXXXX for U+10000+.

Common patterns

ASCII-safe logging
When the log destination cannot handle UTF-8, ascii() guarantees safe output.
log.error("bad name: %s", ascii(name))
Round-trip via eval
ascii(x) is designed so eval(ascii(x)) recreates x for simple types.
s = ascii("café")
# "'caf\xe9'"
eval(s)   # "café"
Diagnose invisible characters
When two strings look the same but compare unequal, ascii() reveals hidden characters.
print(ascii(mystery_string))
# reveals BOM, zero-width joiners, etc.

Examples

1. Plain ASCII
ascii("hello")
Returns
"'hello'"
2. Accent
ascii("café")
Returns
"'caf\\xe9'"
3. Emoji
ascii("hi 😀")
Returns
"'hi \\U0001f600'"
4. Cyrillic
ascii("Привет")
Returns
"'\\u041f\\u0440...'"
5. Newline shown
ascii("a\nb")
Returns
"'a\\nb'"
6. Compare with repr
repr("café") ascii("café")
Returns
'café' vs 'caf\xe9'

Pitfalls

1. ascii vs repr — same escape rules for control chars, different for non-ASCII
Both quote strings and escape newlines / tabs / backslashes. The difference is only above U+007F: repr keeps the character as-is; ascii escapes it.
Assumed identical
repr("café") == ascii("café")
False
Different scopes
repr shows Unicode as Unicode; ascii escapes it
2. Emoji become long \U escapes
Emoji sit above U+FFFF, so they become 8-digit \U escapes. Output can grow surprisingly long for otherwise-short strings.
10-character escape
ascii("😀")
'\\U0001f600' # 10 chars for one grapheme
Use repr in UTF-8
repr("😀")
'😀'
3. Not the same as encode("ascii", errors="backslashreplace")
ascii() returns a str — a repr-shaped string with escapes. encode("ascii", errors="backslashreplace") returns bytes and does NOT add the surrounding quotes.
Wrong output type
"café".encode("ascii", errors="backslashreplace")
b'caf\\xe9' # bytes, no quotes
ascii() for str
ascii("café")
'\'caf\\xe9\'' # str with quotes

When to use

Use it
  • ASCII-only log destinations (older syslog, protocols with limited charsets)
  • Diagnostic output where non-ASCII characters would mangle
  • Detecting invisible zero-width or BOM characters
  • Environments where the terminal cannot render UTF-8
Reach for something else
  • Modern UTF-8 environment → repr() is more readable
  • JSON serialization → json.dumps has its own ensure_ascii option
  • Displaying user-facing text → str() and print()
  • Debug output that a human will read → repr() shows Unicode as Unicode

Notes

Complexity
O(n) in the output length
Return
str — always, with only ASCII characters
CPython impl
Python/bltinmodule.c :: builtin_ascii
Memory
Allocates one string; may be longer than input for non-ASCII
Thread-safe
Yes for immutable inputs

FAQ

Both quote strings and escape control chars. repr keeps non-ASCII characters as-is (utf-8 safe). ascii escapes non-ASCII into \x, \u, or \U sequences. Use repr in UTF-8 environments; ascii when the sink cannot handle non-ASCII.

History

3.0
ascii() introduced to fill the gap left by Python 2's bytes-oriented repr behavior.