Python 3.15 reached its final release on October 9, 2026, and the switch of the default encoding to UTF-8 is the change most likely to affect existing code first. It also adds lazy import, which defers module loading until first use, the immutable dictionary frozendict, and a new sampling profiler called Tachyon. Before upgrading, start by checking whether the code that opens files sets encoding explicitly (as of October 10, 2026).
According to the 3.15.0 release announcement on the official Python blog, 1,012 people contributed 5,643 commits since 3.14. Detailed behavior is covered in Python 3.15 What's New.
Python 3.15 new features at a glance
The release changes the interpreter, standard library, type hints, C API, and build. Here are the changes regular developers will meet first.
| Change | Details | PEP |
|---|---|---|
| UTF-8 default encoding | I/O defaults to UTF-8 regardless of the system locale | 686 |
| lazy import | Loads a module on first use, as in lazy import json | 810 |
| frozendict | Built-in immutable mapping type | 814 |
| sentinel | Built-in type for creating unique sentinel values | 661 |
| Unpacking in comprehensions | Use * and **, as in [*L for L in lists] | 798 |
| profiling package, Tachyon | Tracing and sampling profilers in one package | 799 |
| TypedDict extra items, TypeForm | Type hint extensions | 728, 747 |
The experimental JIT compiler also improved. The announcement says it is 7 to 8% faster (geometric mean) than the standard interpreter on x86-64 Linux, and 11 to 12% faster than the tail-calling interpreter on AArch64 macOS. The two figures use different baselines, so do not compare them side by side.
What the Python default encoding change to UTF-8 means
From 3.15, a call like open('flying-circus.txt') opens the file as UTF-8 even without encoding. The official docs say UTF-8 becomes the default regardless of the system environment (PEP 686). So existing code that opens files without encoding will read them as UTF-8 on 3.15. If a file is stored in another encoding, the result of reading it may change.

If you need the old behavior, use the environment variable PYTHONUTF8=0 or the run option -X utf8=0. The real fix is to set encoding explicitly. Where you truly need the system locale encoding, use encoding='locale' (supported since 3.10). To find affected code, use the opt-in encoding warning described in the io module docs. On 3.10 or later, run python -X warn_default_encoding app.py. Every open() call that lacks encoding prints an EncodingWarning, so when the warnings reach zero, you have finished making encodings explicit.
PYTHONUTF8=0 python app.py
python -X utf8=0 app.py
How to use lazy import to cut startup time
lazy import (PEP 810) is syntax that adds lazy at the top of a module to defer loading until first use. The announcement says explicit lazy imports reduce startup time.

lazy import json
lazy from pathlib import Path
print("Starting up...") # json, pathlib은 아직 완전히 로딩되지 않음
data = json.loads('{"key": "value"}') # 이 시점에 json 로딩
There are limits. It works only at module top level. Using it inside a function, a class body, or try/except/finally raises a SyntaxError. A loading failure also shows up as an exception on the line that first uses the module, not on the import line, so the location of a missing-module error changes. To apply it globally, use -X lazy_imports=all or the PYTHON_LAZY_IMPORTS environment variable. The default is normal. Code that must also run on versions before 3.15 can get the same effect with __lazy_modules__ = ["json", "pathlib"].
frozendict, sentinel, and unpacking in comprehensions
frozendict is a mapping whose values cannot be changed. It is not a subclass of dict, so code that checks types with isinstance(arg, dict) must switch to isinstance(arg, (dict, frozendict)) or use collections.abc.Mapping. If all keys and values are hashable, the frozendict is hashable too (PEP 814).
a = frozendict(x=1, y=2)
a['z'] = 3 # TypeError: 'frozendict' object does not support item assignment
Unpacking in comprehensions (PEP 798) shortens code that flattens nested lists. [*L for L in lists] gives the same result as [x for L in lists for x in L]. For sets, write {*s for s in sets}, and for dictionaries, {**d for d in dicts}. sentinel (PEP 661) is a built-in type that creates unique sentinel values with a concise representation. Its identity is preserved after copying, and you can use it in type expressions with the | operator.
The Tachyon profiler and the profiling package
PEP 799 created the profiling package. It has two parts: profiling.tracing, which records every function call (the new home of the old cProfile), and profiling.sampling (Tachyon), which samples the stack at regular intervals. cProfile stays as a compatibility alias, but the profile module is deprecated and is scheduled for removal in 3.17.
Tachyon can attach to a running process without code changes or a restart. You can pick the time basis from wall (default), cpu, and gil. It samples at up to 1,000,000Hz, and output formats include pstats, collapsed, flamegraph, gecko, and heatmap. For usage details, continue with the Tachyon section of What's New.
What to check before upgrading to Python 3.15
These items come from the official compatibility notes, ordered by how likely they are to hit real code.
| Check | What changed | What to do |
|---|---|---|
| File reads and writes | Default encoding is UTF-8 | Set encoding explicitly or use PYTHONUTF8=0 |
Use of __cached__ | Deprecated since 3.13 and now no longer set | Use __spec__.cached |
import lines in .pth files | Silently deprecated | Review the matching .start file format |
tarfile extraction | Rejected members are not extracted | Check for missing extracted files |
importlib.metadata | Raises MetadataNotFound when metadata is missing | Add exception handling |
argparse | suggest_on_error defaults to True | Check tests that depend on the error message format |
profile module | Deprecated, removal planned for 3.17 | Move to profiling |
The announcement notes that on macOS 27.0, opening a dialog menu in IDLE or tkinter can freeze the app. The cause was reported as a behavior change in macOS 27.0, and the tracking issue is #158053. If you use that environment, test your IDLE workflow first.

Start by creating a separate virtual environment with the new version and running your existing tests. Run with encoding warnings on to find calls missing encoding. Once tests pass and the warnings are cleared, move to your deployment environment. To finish the check, confirm that python --version prints 3.15.0 in the new environment and that a text file containing Korean characters reads without garbled text. Your task for today: search the project for open( and count the lines without encoding.
Frequently asked questions
Can I upgrade to Python 3.15 right away?
For a production service, run your tests in a separate environment first. Among the official compatibility notes, code that opens files without encoding, __cached__, and the tarfile extraction change are the most likely to hit existing code first.
How do I turn off the UTF-8 default change?
You can keep the old behavior with the PYTHONUTF8=0 environment variable or the -X utf8=0 option. In the long run, though, setting encoding explicitly in your code is safer across versions and operating systems.
Can I use lazy import inside a function?
No. It is allowed only at module top level. Inside a function, a class body, or a try block, it raises a SyntaxError.
Found this useful? Share it
Latest posts
Kakao Share Thumbnail Not Showing? Here's the Fix (JavaScript SDK 2025)
Learn why Kakao Share thumbnails don't appear even with a valid imageUrl, and fix it using scrapImage to convert your URL into a KAGE CDN URL. Step-by-step guide.
How to Generate CRM User Manuals in 20 Minutes with Claude Code Sub-Agents
Learn how Claude Code sub-agents can analyze your CRM codebase and auto-generate user manuals and visual guidebooks in just 20 minutes. See the real-world results.
GEO Generative Engine Optimization: The Complete 2025 AI Marketing Strategy Guide
Learn what GEO (Generative Engine Optimization) is, how it differs from traditional SEO, and discover 5 proven AI marketing strategies to get cited by AI search engines in 2025.
Related projects
Get new posts by email
Insights on marketing, analytics, and dev, delivered to your inbox.

