`UnicodeDecodeError` in `deduperreload` on Windows (first %load_ext autoreload) · Issue #15193 · ipython/ipython · GitHub
Skip to content

UnicodeDecodeError in deduperreload on Windows (first %load_ext autoreload) #15193

Description

@danielmader

Summary

On Windows systems with non-UTF-8 default encoding (e.g., cp1252), the first execution of the magic command %load_ext autoreload in a Jupyter notebook fails with a UnicodeDecodeError when the IPython extension deduperreload attempts to read Python Standard Library module files.

Environment

  • IPython version: 9.10.0
  • Python version: 3.13.11
  • Platform: Windows
  • System default encoding: cp1252 (Windows-1252)
  • Jupyter: JupyterLab / VS Code Notebooks

Error Description

When running %load_ext autoreload for the first time in a fresh IPython kernel, the following traceback is printed:

Failed to read module file 'C:...\python\Lib\urllib\parse.py' for module 'urllib.parse': UnicodeDecodeError
...
ModuleNotFoundError: No module named 'autoreload'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "c:...\venv\Lib\site-packages\IPython\extensions\deduperreload\deduperreload.py", line 219, in update_sources
self.source_by_modname[new_modname] = f.read()
File "C:...\python\Lib\encodings\cp1252.py", line 23, in decode
return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 1981: character maps to <undefined>

This error is repeated for multiple Standard Library modules (e.g., functools.py, re._casefix.py, _strptime.py).

Workaround: Running the command a second time succeeds without errors.

Root Cause

In IPython/extensions/deduperreload/deduperreload.py, line 219, the update_sources() method opens Python module files without specifying an encoding:

with open(fname, "r") as f:
    self.source_by_modname[new_modname] = f.read()

Proposed Fix

Explicitly specify encoding="utf-8" in the file open operation:

--- a/IPython/extensions/deduperreload/deduperreload.py
+++ b/IPython/extensions/deduperreload/deduperreload.py
@@ -216,7 +216,7 @@ class SourceDiffChecker:
                 continue
             try:
-                with open(fname, "r") as f:
+                with open(fname, "r", encoding="utf-8", errors="replace") as f:
                     self.source_by_modname[new_modname] = f.read()
             except Exception as e:
                 logger = logging.getLogger("autoreload")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions