Skip to content
Putting technology to work.
Insights to guide decisions and action.

Search articles

Python 3.15 defaulting to UTF-8 and CP932 CSV files

Table of contents · 7 items

You aggregate order data CSVs exported from your core system with a Python script running on a Windows PC. The daily morning task has always worked fine, but the day after you replace the PC or reinstall Python, it stops with UnicodeDecodeError. With Python 3.15, released on October 9, 2026, this kind of failure can occur.

Starting with 3.15, the encoding used when encoding is not specified in open() and similar functions is UTF-8 in all environments, including Windows. Through 3.14, Windows used the encoding of the PC's locale (the ANSI code page). Scripts that read CP932 files without encoding will behave differently here. We confirmed the changes in the documents in the Python repository and, based on the results of reproducing them locally, summarize how to check and how to fix.

What changed in 3.15

"What's new in Python 3.15" in the v3.15.0 tag opens with "Python 3.15 was released on 9 October 2026." and lists "UTF-8 as the default encoding" as one of the major changes. The text reads as follows.

Python now uses UTF-8 as the default encoding, independent of the system’s environment. This means that I/O operations without an explicit encoding, for example, open('flying-circus.txt'), will use UTF-8.

This change comes from PEP 686, "Make UTF-8 mode default," and means that "UTF-8 mode," which could be opted into since 3.7, is now enabled by default. The PEP explains that in addition to files, standard I/O and pipes also become UTF-8, and describes the scope of impact as follows.

Most Unix systems use UTF-8 locale and Python enables UTF-8 mode when its locale is C or POSIX. So this change mostly affects Windows users.

It also states that "this change may cause UnicodeError, mojibake, or even silent data corruption." This means that not only can reading fail, but the encoding of written files can change, causing garbled text on the receiving side.

Comparison of 3.14 and earlier versus 3.15. open() without an encoding uses the locale encoding (ANSI code page) on Windows through 3.14, and UTF-8 in 3.15. Reading a CP932 CSV raises UnicodeDecodeError, and written files become UTF-8. The fix is to specify the encoding explicitly (cp932, utf-8, locale); as a temporary measure, PYTHONUTF8=0 restores the previous behavior

Reproducing it locally

Because we could not set up Python 3.15 in the test environment for this article, we enabled UTF-8 mode on Python 3.11.17 on Linux (-X utf8=1) to reproduce the 3.15 default state. We prepared the following CSV written in CP932.

受注番号,得意先,金額
1001,株式会社サンプル,12000
1002,髙橋商店,8000

Running a script that reads it without specifying encoding stopped at the first character.

$ python3 -X utf8=1 read_orders.py orders_cp932.csv
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8e in position 0: invalid start byte

Specifying encoding='cp932' allowed it to be read, including variant kanji characters such as the one used in the surname "Takahashi."

$ python3 -X utf8=1 -c "import csv; print(list(csv.reader(open('orders_cp932.csv', encoding='cp932', newline='')))[2])"
['1002', '髙橋商店', '8000']

The writing side changes too. In the same UTF-8 mode, writing the word for "customer" to open('out.csv', 'w') produced file contents as a UTF-8 byte sequence (e5 be 97 e6 84 8f e5 85 88). If another system or import process has been receiving the data as CP932, the text will be garbled there.

The reproduction was done on Linux, not by comparing 3.14 and 3.15 on a Windows PC. You can check which encoding Windows uses through 3.14 by running the following command on the target PC. The Python documentation explains that on Windows, locale.getencoding() returns the ANSI code page.

python -c "import locale; print(locale.getencoding())"

Scripts that read or write without encoding on PCs that display cp932 here are what you need to check this time.

Identifying affected code

As a way to deal with compatibility issues, PEP 686 suggests disabling UTF-8 mode and then using EncodingWarning to find affected locations. On 3.10 and later, running with -X warn_default_encoding emits a warning wherever encoding is omitted.

$ python3 -X utf8=0 -X warn_default_encoding read_orders.py orders_utf8.csv
read_orders.py:2: EncodingWarning: UTF-8 Mode affects locale.getpreferredencoding(). Consider locale.getencoding() instead.
read_orders.py:3: EncodingWarning: 'encoding' argument not specified

The first line is the warning for the line that calls locale.getpreferredencoding(), and the second is the warning for the open() line that omits encoding. Because warnings include line numbers, you can build a list of fixes directly. Warnings appear only for lines that actually run, so for branches that normally do not run (such as month-end-only processing), supplement with a search of the source.

grep -rnE "open\(|read_text\(|write_text\(|text=True|universal_newlines|getpreferredencoding" --include=*.py .

text=True in subprocess is also affected. PEP 686 says that if you want to keep using the previous encoding for pipes, you should get by with UTF-8 mode disabled until you replace text=True with an explicit encoding="utf-8" or encoding="locale".

How to Fix

  1. If the file's encoding is known, write it explicitly. Use encoding='cp932' for CP932 CSVs and encoding='utf-8' for UTF-8. What's new also recommends that you "ensure that an explicit encoding argument is always provided"
  2. If you want to match the PC's locale, use encoding='locale'. Available since 3.10, it uses the locale encoding even in UTF-8 mode
  3. If you cannot fix it right away, restore the previous behavior with the environment variable PYTHONUTF8=0 or -X utf8=0. If the script is launched from Task Scheduler or similar, add it to that launch configuration. Use this only as a stopgap until the fix

On the writing side, specify encoding explicitly according to the receiving party's requirements. How to agree on CSV encoding, line endings, and BOM handling is covered in detail in Distributing CSV files is hard: designing business data exchange.

When to fix it by

There is no need to rush the upgrade to 3.15. According to PEP 790 (the 3.15 release schedule), 3.15 will receive bug fixes for about two years, followed by security fixes until around October 2031. Versions 3.14 and earlier can also be used until their respective end dates.

What to watch out for are situations where you end up on 3.15 unintentionally. Replacing a PC, reinstalling Python, or updating CI or container images can install the latest version. The editorial team recommends making encoding explicit ahead of time, even if you have no plans to upgrade to 3.15. Because the result is the same in every version, you will not be caught off guard when you upgrade.

If you are also updating dependency packages, vulnerability checks are covered in Continuously checking Python dependency vulnerabilities with uv audit, and settings to avoid freshly released versions are covered in Pip 26.1 Dependency Cooldowns.

Scope of verification

On October 11, 2026, we retrieved and checked Doc/whatsnew/3.15.rst, Doc/library/os.rst, Doc/library/locale.rst, and Include/patchlevel.h (PY_VERSION "3.15.0", release level FINAL) from the v3.15.0 tag of python/cpython, and PEP 686 and PEP 790 from python/peps, via raw.githubusercontent.com (document research). We also enabled and disabled UTF-8 mode on Python 3.11.17 on Linux to check reading CP932 and UTF-8 CSVs, the byte sequences of written files, and the -X warn_default_encoding warnings (hands-on testing). On October 16, 2026, we also checked the 3.15.0 release page on python.org (Release date: Oct. 9, 2026, with PEP 686 among the major changes). We have not tested Python 3.15 itself or on a Windows PC.

For taking inventory of scripts running in your company or rebuilding CSV integrations, contact us through Development, AI, and automation consultations.

References

Share this articleXFacebook
Kakeru Suzuki

Fascinated by the possibilities of technology, has had a deep interest in programming and digital art since student days

Turn this article's theme into your company's next step

Concrete steps forward for your organization.

We organize your desired architecture, legacy systems, and operational requirements to formulate your next steps toward execution.

  • Desired architecture
  • Integration with existing environments
  • Operational requirements
Consult on development & operations initiatives

You can consult with us from the initial conceptual stage. Details from this article will be carried over to the inquiry form.

Receive the latest articles by email