Najważniejsze w skrócie
- Python 3.15.0 wyszedł 9 października 2026 r., a aktualna wersja poprawkowa to 3.15.2. Wersja 3.15 będzie wspierana do października 2031 r.
- Python 3.10 od 1 października 2026 r. nie dostaje poprawek bezpieczeństwa. Aplikacje na tej wersji trzeba przenieść w pierwszej kolejności, a 3.11 ma wsparcie już tylko do października 2027 r.
- Najciekawsze nowości to leniwe importy (
lazy import), wbudowane typyfrozendictisentinel, rozpakowanie*i**w wyrażeniach listowych oraz profiler próbkujący Tachyon. - Największa zmiana zachowania:
open()bez parametruencodingzawsze używa UTF-8. Na serwerach z Windows może to zmienić odczyt plików z polskimi znakami. - Na produkcję polecamy 3.15 dopiero wtedy, gdy obsługują ją wszystkie biblioteki aplikacji. Django obsługuje Pythona 3.15 od wersji 6.1.3, a Django 5.2 LTS kończy na 3.14.
Wersje Pythona i do kiedy mają wsparcie
Nowa wersja Pythona ukazuje się co roku w październiku i jest wspierana przez 5 lat. Od wersji 3.13 przez pierwsze 2 lata dostaje pełne poprawki błędów, a potem już tylko poprawki bezpieczeństwa (wcześniej okres pełnych poprawek trwał 18 miesięcy). Tak wygląda stan na listopad 2026 r.:
| Wersja | Wydana | Stan | Koniec wsparcia |
|---|---|---|---|
| 3.10 | październik 2021 r. | bez wsparcia | 1 października 2026 r. |
| 3.11 | październik 2022 r. | tylko poprawki bezpieczeństwa | październik 2027 r. |
| 3.12 | październik 2023 r. | tylko poprawki bezpieczeństwa | październik 2028 r. |
| 3.13 | październik 2024 r. | tylko poprawki bezpieczeństwa | październik 2029 r. |
| 3.14 | październik 2025 r. | pełne wsparcie | październik 2030 r. |
| 3.15 | październik 2026 r. | pełne wsparcie | październik 2031 r. |
Daty według przewodnika dla twórców Pythona (devguide.python.org) i dokumentów PEP z harmonogramami wydań.
Od 1 października 2026 r. ta wersja nie dostaje poprawek bezpieczeństwa, a ostatnim wydaniem jest 3.10.22. Biblioteki też ją porzucają: Django 6.0 i nowsze wymagają Pythona 3.12. Zwykle rozsądniej przejść od razu na 3.13 albo 3.14, niż aktualizować w dwóch krokach.
Leniwe importy: szybszy start aplikacji
Duże aplikacje długo się uruchamiają, bo Python przy starcie wczytuje wszystkie moduły z importów na początku pliku, także te, których w danym uruchomieniu nikt nie użyje. Dotąd obchodziło się to importami wewnątrz funkcji, co utrudniało czytanie kodu. Python 3.15 dodaje słowo kluczowe lazy (PEP 810): moduł wczytuje się dopiero przy pierwszym użyciu nazwy.
lazy import json
lazy from pathlib import Path
print("Start...") # json i pathlib nie są jeszcze wczytane
data = json.loads('{"key": "value"}') # tu wczytuje się json
p = Path(".") # a tu pathlib
Jeśli modułu nie da się wczytać, błąd pojawia się przy pierwszym użyciu, a komunikat pokazuje zarówno to miejsce, jak i linię z importem. lazy działa tylko na poziomie modułu: w funkcji, w klasie albo w bloku try daje SyntaxError, podobnie jak lazy from modul import *.
Leniwe importy można też włączyć dla całej aplikacji bez zmian w kodzie, opcją -X lazy_imports=all albo zmienną PYTHON_LAZY_IMPORTS. Funkcja sys.set_lazy_imports_filter() pozwala ograniczyć to do wybranych modułów, na przykład tylko własnych, a biblioteki zewnętrzne zostawić bez zmian. Kod, który musi działać także na starszych wersjach Pythona, może zamiast słowa lazy podać listę modułów w zmiennej __lazy_modules__:
__lazy_modules__ = ["json", "pathlib"]
import json # w 3.15 leniwie, w starszych wersjach normalnie
import os # zawsze od razu
Gdzie to się opłaca
- Narzędzia wiersza poleceń i skrypty, które przy każdym uruchomieniu korzystają tylko z części funkcji.
- Testy, zadania cykliczne i polecenia administracyjne, które startują wiele razy dziennie.
- Funkcje bezserwerowe, w których liczy się czas zimnego startu.
W serwerach aplikacji, które działają tygodniami, zysk jest mniejszy, bo kod wczytuje się raz. Dokumentacja nie podaje konkretnych liczb, więc start własnej aplikacji najlepiej zmierzyć przed zmianą i po niej, na przykład poleceniem python -X importtime.
frozendict i sentinel: nowe typy wbudowane
frozendict (PEP 814) to niezmienny słownik. Po utworzeniu nie da się do niego nic dopisać. Jeśli jego klucze i wartości są haszowalne, sam też jest haszowalny, więc może być kluczem w innym słowniku albo w pamięci podręcznej. Zachowuje kolejność wstawiania, ale przy porównaniu kolejność nie ma znaczenia.
>>> a = frozendict(x=1, y=2)
>>> a == frozendict(y=2, x=1)
True
>>> a["z"] = 3
TypeError: 'frozendict' object does not support item assignment
Uwaga przy wdrażaniu: frozendict nie dziedziczy po dict. Kod, który sprawdza isinstance(x, dict), go nie rozpozna. Dokumentacja zaleca isinstance(x, (dict, frozendict)) albo sprawdzanie collections.abc.Mapping. Moduły json, pickle i copy obsługują nowy typ.
sentinel (PEP 661) tworzy unikalną wartość specjalną, na przykład oznaczenie, że parametr nie został podany, którą da się odróżnić od None. Taka wartość zachowuje tożsamość przy kopiowaniu, można ją serializować i używać w adnotacjach typów:
MISSING = sentinel("MISSING")
def next_value(default: int | MISSING = MISSING):
if default is MISSING:
...
Rozpakowanie w wyrażeniach listowych
Spłaszczenie listy list albo połączenie kilku słowników wymagało dotąd podwójnej pętli w wyrażeniu albo itertools.chain. Od wersji 3.15 (PEP 798) w wyrażeniach listowych, zbiorach, słownikach i generatorach można użyć * i **:
>>> lists = [[1, 2], [3, 4], [5]]
>>> [*L for L in lists]
[1, 2, 3, 4, 5]
>>> dicts = [{"a": 1}, {"b": 2}, {"a": 3}]
>>> {**d for d in dicts}
{'a': 3, 'b': 2}
To drobna zmiana, ale kod przetwarzający dane (wyniki zapytań, odpowiedzi API, konfiguracje) staje się krótszy i czytelniejszy. Przy słownikach, jak w zwykłym {**a, **b}, późniejsza wartość nadpisuje wcześniejszą.
Profiler Tachyon: pomiar wydajności bez restartu
Python 3.15 zbiera narzędzia do profilowania w pakiecie profiling (PEP 799). profiling.tracing to dotychczasowy cProfile (stara nazwa nadal działa), a nowy profiling.sampling, nazwany Tachyon, to profiler próbkujący. Zamiast śledzić każde wywołanie funkcji, co spowalnia program, co jakiś czas zapisuje stos wywołań.
Z punktu widzenia utrzymania aplikacji najważniejsze jest to, że Tachyon podłącza się do działającego procesu po numerze PID, bez zmian w kodzie i bez restartu. Gdy system na produkcji zwalnia, można sprawdzić, w której funkcji spędza czas, zamiast próbować odtworzyć problem na serwerze testowym.
# podłączenie do działającego procesu
python -m profiling.sampling attach 1234
# uruchomienie skryptu i zapis interaktywnego wykresu płomieniowego (flame graph)
python -m profiling.sampling run --flamegraph script.py
Profiler mierzy czas rzeczywisty (razem z oczekiwaniem na bazę danych i sieć), czas procesora, czas trzymania blokady GIL albo obsługę wyjątków. Wynik można zapisać jako wykres płomieniowy, mapę cieplną z dokładnością do linii kodu, plik dla Firefox Profiler albo oglądać na żywo w terminalu. Jest też tryb dla kodu asynchronicznego. Podłączenie do działającego procesu wymaga uprawnień: w Linuksie konta root, uprawnienia CAP_SYS_PTRACE albo zmiany ustawienia ptrace_scope.
Stary moduł profile jest przestarzały i zniknie w Pythonie 3.17.
Typowanie i czytelniejsze komunikaty błędów
Zespoły, które korzystają z adnotacji typów i narzędzi takich jak mypy czy Pyright, dostają kilka uzupełnień. TypedDict może być zamknięty (closed=True) albo określać typ dodatkowych kluczy (extra_items, PEP 728), co pozwala dokładniej opisać na przykład odpowiedzi API. Doszły też TypeForm (PEP 747) i dekorator @disjoint_base (PEP 800).
class Point(TypedDict, extra_items=int):
x: int
y: int
p: Point = {"x": 1, "y": 2, "z": 3} # poprawne: dodatkowe klucze muszą mieć wartości int
Komunikaty błędów znów są bardziej pomocne. Gdy atrybut jest dostępny przez inny obiekt, Python podpowiada pełną ścieżkę. Gdy ktoś użyje nazwy metody znanej z innego języka, wskazuje jej odpowiednik:
>>> [1, 2, 3].push(4)
AttributeError: 'list' object has no attribute 'push'. Did you mean '.append'?
>>> (1, 2, 3).append(4)
AttributeError: 'tuple' object has no attribute 'append'. Did you mean to use a 'list' object?
Wydajność: JIT, Windows i free-threading
- Kompilator JIT nadal jest eksperymentalny, ale wyraźnie się poprawił. Według dokumentacji w zestawie testów pyperformance przyspiesza średnio o 7 do 8% na Linuksie x86-64 i o 11 do 12% na macOS z procesorami Apple. Wyniki poszczególnych testów wahają się od około 15% spowolnienia do ponad dwukrotnego przyspieszenia. Przy kompilacji ze źródeł JIT domyślnie nie jest wbudowywany.
- Windows: oficjalne 64-bitowe instalatory używają nowego interpretera (tail-calling), który według dokumentacji jest średnio szybszy o 15 do 20%.
- Free-threading, czyli Python bez blokady GIL, to nadal osobna, opcjonalna wersja interpretera. W 3.15 dostała stabilne ABI dla rozszerzeń w C (PEP 803), co ułatwi bibliotekom przygotowanie pakietów. Narzut na kod jednowątkowy to według dokumentacji od około 1% (macOS na procesorach ARM) do 8% (Linux x86-64).
- Biblioteka standardowa: między innymi kodowanie base64 jest 2 razy szybsze, a dekodowanie 3 razy.
W typowej aplikacji internetowej czas i tak zabierają głównie baza danych i sieć. Nowa wersja Pythona rzadko naprawia wolną aplikację. Częściej pomoże profiler, który pokaże, gdzie naprawdę leży problem.
Co może zepsuć aktualizację
Najważniejsza zmiana zachowania dotyczy kodowania znaków. Od wersji 3.15 funkcja open() i inne operacje na plikach bez parametru encoding zawsze używają UTF-8 (PEP 686), niezależnie od ustawień systemu. Na Linuksie zwykle nic się nie zmieni. Na Windows z polskimi ustawieniami domyślnym kodowaniem było dotąd cp1250, więc skrypty, które bez podanego kodowania czytają eksporty z systemów księgowych albo pliki CSV z Excela, mogą po aktualizacji źle odczytać polskie znaki.
# kodowanie zawsze podajemy jawnie
with open("eksport.csv", encoding="cp1250") as f:
...
# ostrzeżenia o miejscach bez podanego kodowania (od Pythona 3.10)
python -X warn_default_encoding -m pytest
Stare zachowanie można przywrócić zmienną PYTHONUTF8=0, ale lepiej poprawić kod. Inne zmiany, które mogą wymagać poprawek:
- Usunięte moduły
sre_compile,sre_constantsisre_parseoraz metodyload_module()w mechanizmie importu. - Usunięte
http.server.CGIHTTPRequestHandleriPurePath.is_reserved(). datetime.strptime()z dniem miesiąca (%d), ale bez roku zgłaszaValueError. Ostrzeżenie o tym pojawiało się od wersji 3.13.- Wszystkie parametry
sqlite3.connect()poza ścieżką do bazy trzeba podawać z nazwą. unittest:assertWarns()nie połyka już niepasujących ostrzeżeń, więc w wynikach testów mogą pojawić się nowe komunikaty.argparse: przyadd_argument('-f', '-foo')nazwa atrybutu to terazfoo, a nief.
Zapowiedziane usunięcia: w 3.16 zniknie mechanizm polityk pętli zdarzeń w asyncio (set_event_loop_policy() i pokrewne), a w 3.17 moduł profile. Ostrzeżenia o przestarzałych funkcjach najlepiej naprawiać na bieżąco, uruchamiając testy z opcją -W error::DeprecationWarning.
W wersji 3.15.0 równoczesne importy w kilku wątkach mogły się zablokować. Błąd poprawiono w 3.15.2. Na serwery zawsze trafia u nas najnowsza wersja poprawkowa, a nie pierwsze wydanie nowej wersji.
Kiedy i jak przejść na nową wersję
Systemy produkcyjne przenosimy na nową wersję Pythona kilka miesięcy po premierze, gdy wszystkie biblioteki aplikacji mają już gotowe pakiety, a sama wersja dostała pierwsze poprawki. W listopadzie 2026 r. w zupełności wystarczają 3.13 albo 3.14. Pilne są aplikacje na 3.10 i starszych wersjach, a przeniesienie aplikacji z 3.11 trzeba zaplanować przed październikiem 2027 r.
- InwentaryzacjaLista aplikacji, skryptów i zadań cyklicznych z wersją Pythona, systemem i osobą odpowiedzialną. Łatwo pominąć skrypty w harmonogramie zadań i kontenery budowane ze starych obrazów.
- ZależnościSprawdzenie, czy wszystkie biblioteki obsługują docelową wersję i czy żadna nie jest porzucona. W aplikacjach Django decyduje wersja frameworka: Django 6.1.3 i nowsze obsługują Pythona 3.15, a Django 5.2 LTS kończy na 3.14 (więcej w poradniku o Django 6).
- Testy na nowej wersjiTesty automatyczne na docelowej wersji, z ostrzeżeniami o kodowaniu i przestarzałych funkcjach. Jeśli testów brakuje, przygotowujemy listę najważniejszych scenariuszy do sprawdzenia ręcznie.
- Środowisko testoweNowy obraz kontenera albo środowisko na serwerze testowym, z kopią danych. Sprawdzamy też zadania w tle, eksporty i integracje z innymi systemami.
- Wdrożenie z planem powrotuPoprzednia wersja zostaje gotowa do przywrócenia. Po wdrożeniu obserwujemy logi, błędy i czasy odpowiedzi.
- Wersja Pythona każdej aplikacji i skryptu zapisana w jednym miejscu.
- Aplikacje na Pythonie 3.10 i starszym przeniesione w pierwszej kolejności.
- Wszystkie biblioteki obsługują docelową wersję, żadna nie jest porzucona.
- Jawne
encoding=przy każdymopen()i odczycie plików CSV. - Testy uruchamiane z
-X warn_default_encodingi-W error::DeprecationWarning. - Na serwerach najnowsza wersja poprawkowa Pythona (dla 3.15 co najmniej 3.15.2).
- Kontenery budowane z aktualnego obrazu bazowego i regularnie przebudowywane.
Najczęstsze pytania
Czy warto od razu przenieść aplikację na Pythona 3.15?
Zwykle nie od razu. Nowe funkcje są wygodne, ale w systemie produkcyjnym ważniejsze jest to, żeby nową wersję obsługiwały wszystkie biblioteki. Rozsądny moment to kilka miesięcy po premierze. Wyjątkiem są aplikacje na wersjach bez wsparcia: te trzeba przenieść jak najszybciej, choćby na 3.13 albo 3.14.
Czy Python 3.10 jest jeszcze bezpieczny?
Nie dostaje już poprawek bezpieczeństwa. Wsparcie skończyło się 1 października 2026 r., a ostatnim wydaniem jest 3.10.22. Aplikacja będzie działać, ale nowe podatności w interpreterze i bibliotece standardowej nie zostaną załatane.
Czy Django działa z Pythonem 3.15?
Tak, od wersji Django 6.1.3 z listopada 2026 r. Django 5.2 LTS obsługuje Pythona od 3.10 do 3.14. Wagtail obsługuje Pythona 3.15 od wersji 8.1.
Czy JIT przyspieszy moją aplikację?
Lepiej na to nie liczyć. JIT w Pythonie 3.15 jest eksperymentalny, średni zysk w testach to kilka procent, a różnice między programami są duże. W aplikacjach internetowych czas zwykle zabierają baza danych i sieć.
Czy Python bez GIL (free-threading) nadaje się na produkcję?
To oficjalnie wspierana, ale opcjonalna wersja interpretera. Ma sens przy obliczeniach w wielu wątkach, pod warunkiem że obsługują ją wszystkie używane rozszerzenia w C. W typowej aplikacji internetowej nie ma powodu, żeby się z tym spieszyć.
Źródła
- Python: What's New in Python 3.15
- Python.org: wydanie Python 3.15.0
- Python Developer's Guide: stan wersji Pythona
- PEP 810: Explicit lazy imports
- PEP 686: Make UTF-8 mode default
- Python: dokumentacja profiling.sampling (Tachyon)
- Django: obsługiwane wersje Pythona
Stan na 6 listopada 2026 r. Dane o wydajności pochodzą z dokumentacji Pythona; w konkretnej aplikacji wyniki mogą być inne.