keepcalculator

06 Numbers and Powers

Python Encoding Field Notes: When Default Isn’t UTF-8

Card No. 06·38596 · Updated · Standard formula, shown below

The calculator on this card is switched off while it is checked. The formula is below, and the worked example shows how to do the sum by hand.

This article explains how to handle file encoding in Python when the preferred encoding is not the open() default. You will learn how to specify an encoding explicitly, why it matters, and how to avoid common pitfalls like UnicodeDecodeError.

Formula

The calculator estimates the number of characters a file of a given size can hold, based on the average bytes per character for the chosen encoding. The formula is:

Approx. characters = (File size in KB × 1024) / (1 + Encoding overhead % / 100)

Where:

  • File size (KB) – the size of the file in kilobytes.
  • Encoding overhead (%) – the average number of bytes per character minus 1, expressed as a percentage. For UTF-8, this is typically 0% for ASCII text, 100% for accented characters (2 bytes), 200% for CJK (3 bytes). For UTF-16, it’s 100% overhead (2 bytes per char).

This is a rough estimate; actual character count depends on the specific characters used.

Worked Example

Using the defaults: File size = 10 KB, Encoding overhead = 10%.

  1. Convert KB to bytes: 10 × 1024 = 10240 bytes.
  2. Add overhead: 1 + 10/100 = 1.1.
  3. Divide: 10240 / 1.1 ≈ 9309 characters.

The calculator shows 9309 characters.

Why Encoding Matters

Python’s open() function uses a default encoding that depends on the platform and locale. On many Linux systems, this is UTF-8, but on Windows it might be cp1252 or another legacy encoding. When you read or write files with non-ASCII characters (like é, 中文, or emoji), using the wrong encoding can cause data corruption or UnicodeDecodeError. Specifying the encoding explicitly ensures your code behaves consistently across environments.

How to Specify Encoding

You pass the encoding parameter to open():

with open('file.txt', 'r', encoding='utf-8') as f:
    data = f.read()

with open('file.txt', 'w', encoding='utf-8') as f:
    f.write('café')

For reading, if the file is not in the specified encoding, Python raises UnicodeDecodeError. For writing, it may raise UnicodeEncodeError if a character cannot be represented.

Choosing the Right Encoding

Common encodings include:

  • UTF-8 – the default on most modern systems, supports all Unicode characters, variable-length (1-4 bytes).
  • UTF-16 – used by Windows internals, good for files with many non-ASCII characters, but includes a BOM (byte order mark) unless you specify utf-16-le or utf-16-be.
  • cp1252 – legacy Windows encoding for Western European languages, not fully Unicode.
  • ISO-8859-1 – similar to cp1252 but with fewer characters.

For new files, UTF-8 is almost always the best choice. For reading legacy files, you may need to detect the encoding using a library like chardet (not built-in) or try multiple encodings.

Common Problems and Solutions

UnicodeDecodeError – occurs when reading a file with a character that doesn’t map to the specified encoding. Solutions:

  • Try a different encoding (e.g., latin-1 reads any byte but may produce mojibake).
  • Use errors='replace' or errors='ignore' to handle invalid bytes gracefully.
  • Open in binary mode and decode manually.

UnicodeEncodeError – occurs when writing a character not representable in the target encoding. Solutions:

  • Use UTF-8.
  • Use errors='replace' to replace with ‘?’.

BOM issues – UTF-16 files start with a BOM (U+FEFF). If you open in text mode, Python strips it automatically for utf-16, but for utf-8-sig you need to specify that to strip a BOM if present.

Best Practices

  • Always specify encoding when opening text files, even if you think it’s the default.
  • Use UTF-8 for all new files.
  • When reading unknown files, try UTF-8 first, then fall back to a list of common encodings.
  • For cross-platform code, set PYTHONUTF8=1 environment variable or use sys.setdefaultencoding (not recommended) to force UTF-8.

Frequently Asked Questions

What is the default encoding in Python 3?

It depends on the platform and locale. On most Linux and macOS systems, it’s UTF-8. On Windows, it’s often cp1252, but this can vary. You can check with sys.getdefaultencoding().

How do I read a file with an unknown encoding?

Try a few common encodings in a loop, or use a library like chardet to guess. For a quick fix, open in binary mode and decode with errors='replace' to avoid crashes.

What is the difference between ‘utf-8’ and ‘utf-8-sig’?

‘utf-8’ does not add a BOM when writing, and when reading, it treats a BOM as a regular character (U+FEFF). ‘utf-8-sig’ writes a BOM at the start and strips it when reading. Use ‘utf-8-sig’ for compatibility with Windows tools that expect a BOM.

Why do I get a UnicodeDecodeError even though the file is UTF-8?

Possibly the file is not valid UTF-8 (e.g., it has a BOM or is actually another encoding). Try opening with encoding='utf-8-sig' if a BOM might be present, or use errors='replace' to see where it fails.

Can I change the default encoding for all open() calls?

You can set the environment variable PYTHONUTF8=1 before starting Python, or call sys.setdefaultencoding() (deprecated and removed in Python 3.9). The recommended approach is to always pass the encoding parameter explicitly.

What does ‘errors’ parameter do?

It controls how encoding/decoding errors are handled. Common values: ‘strict’ (default, raises exception), ‘replace’ (replaces with ‘?’), ‘ignore’ (drops the character), ‘backslashreplace’ (uses \xNN escapes).

Related

Formula used
in t | File size (KB) | KB | 10 | 0 | 1000000
in e | Encoding overhead (%) | % | 10 | 0 | 100
out chars | Approx. characters | chars | (t * 1024) / (1 + e / 100) | 0

Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →