Yesterday, 09:00 AM
Steering Council member and Release Manager Pablo Galindo Salgado opened the Language Summit this year to propose solutions to a problem that everyone who’s used Python has encountered at least once before.
![[Image: pablo-lectern.DPzf_KbF_Zq2zjj.webp]](https://blog.python.org/_astro/pablo-lectern.DPzf_KbF_Zq2zjj.webp)
Photo by EuroPython (CC BY-NC-SA 4.0)
The issue manifests as seemingly random exceptions from modules like , , or for names you know are correct. Why is the standard library suddenly raising errors?
The issue is usually that a module is “shadowing” the standard library module from a higher-precedence location in, such as your current working directory or a directory on . There is probably a file named or in your project, and that module takes precedence over the standard library module of the same name, which is only noticed once you start using the module elsewhere in your project.
This issue is caused by Python’s flat module namespace; there is no delineation between what is part of the standard library and what are third-party modules, either dependencies or project code.
Pablo noted that there is a low-cost option that solves this issue, available since Python 3.11: the -P option, which, according to the documentation, “doesn’t prepend a potentially unsafe path to”, such as the current working directory. The problem is that most users are not running Python with this option enabled, or are depending on the current working directory being importable because they don’t install their own project code into the environment.
New standard library module names are constrained
The problem goes beyond being confusing to users. Pablo explained that the flat namespace means that core developers often need to choose “awkward” names for new modules due to what’s already in use on the Python Package Index (PyPI). This restriction applies even when a module is being adopted from PyPI into the standard library, such as PyYAML, which provides the module. This is the reason that many new standard library modules have been suffixed with “lib” (such as or ) or are unexpectedly named (such as instead of ).
What is one potential solution? Adding a new top-level namespace
for all standard library modules. Pablo suggested the name
for this namespace, so users who want to guarantee they are importing
a standard library module would or , for example.
Pablo assured everyone that without the namespace
would keep working basically forever (“We can’t break the world, that would be bad”).
But Pablo didn’t exclude the idea of introducing new modules exclusively
in the namespace as a method for encouraging users to begin adopting
the new namespace:
![[Image: pablo-slide.Dr0ZbgCI_2mABAx.webp]](https://blog.python.org/_astro/pablo-slide.Dr0ZbgCI_2mABAx.webp)
Photo by EuroPython (CC BY-NC-SA 4.0)
Python wouldn’t be alone, either. Many other programming languages have
already namespaced their standard library (or equivalent):
LanguageNamespaceNotesRust/C++Reserved from day oneJavaEnforced at the classloaderGoStandard library known by path shapeNode.jsRetrofitted, unspoofablePython(⚠) Flat, unreserved
A tempting door opens: unbundling the standard library
Pablo shared that a potential side effect of reserving a new top-level namespace
for the Python standard library is that the standard library
could then more easily be “unbundled”. Unbundling the standard library
would mean that the stdlib modules would be upgradeable separately
from the Python interpreter and independently of each other, likely
distributed through PyPI.
Unbundling the standard library would provide a few benefits:
But there are trade-offs to unbundling, and we know of one concrete example.
Ruby “gemified” its standard library and ran into issues, such as long
deprecation periods ( took three release cycles), warnings from
transitive dependencies, and a CVE in the gem that went unpatched because the gem wasn’t
listed in, the Ruby equivalent of a package manifest.
Discussion
Kushal Das shared that the shadowing issue was a “big problem for newcomers”, especially first-time Python users writing code doing arithmetic in a file named.
![[Image: jukka.Dqbr2b0J_NaBmE.webp]](https://blog.python.org/_astro/jukka.Dqbr2b0J_NaBmE.webp)
Photo by Hugo van Kemenade (CC BY-NC-SA 4.0)
Jukka Lehtosalo shared that he had also “personally encountered this problem”, and asked if there was “data about how often this happens”. Pablo didn’t have concrete data and shared that the error message has improved in recent Python versions.
Pablo didn’t want to over-focus on the shadowing issue and instead wanted to focus on what he believed was the larger issue: how the flat namespace affects how core developers choose standard library module names.
David Hewitt wondered whether there is a “security edge” to this proposal, positing that core developers are “more familiar with what is in the standard library” compared to a beginner, and asked whether this change could help learners know what is included in Python and what isn’t. Pablo pushed back on the security angle: “the standard library is huge, we could do [standard library module] trivia and we’d all fail”. He concluded that this could be another positive reason to adopt the proposal, but he didn’t want to oversell this aspect, either.
Guido van Rossum asked whether every stdlib module would eventually need to move under this proposal, which Pablo confirmed. As a follow-up, Guido asked whether this would mean touching imports across the entire standard library, which Pablo also confirmed, noting that this migration could be “mostly mechanical” and could include freezing all modules.
Peter Bierma asked whether the new namespace would add performance costs, to which Pablo answered that the cost would be “effectively zero”.
![[Image: thomas.DqWCNTa1_Z1hujH2.webp]](https://blog.python.org/_astro/thomas.DqWCNTa1_Z1hujH2.webp)
Photo by Hugo van Kemenade (CC BY-NC-SA 4.0)
Thomas Wouters imagined an incremental rollout of the new namespace, proposing that new modules would land under the namespace, with the possibility of a future mode that disables top-level shadowing entirely once enough of the ecosystem has moved.
Stefan Behnel felt that Python “should provide a way to confidently import from the standard library”. He offered a potential solution that would keep most code the same: limiting the proposal to imports. The syntax would be , so the module name would be the same and the namespace wouldn’t appear in user code. This would also avoid the issue of sys.modules duplicating the module. Guido concurred, noting that could be magic. A “special keyword”, Pablo added.
David Hewitt noted the precedent already set by the lazy keyword (new in Python 3.15) for changing the statement without having to introduce a new module.
After a show of hands to get a temperature check on the idea of using a keyword, no one attending “hated the idea” and many attendees “loved the idea”.
Gregory P. Smith provided guidance with his “PEP hat” on, noting that the proposal was potentially trying to solve multiple issues at once. “Keep all the ideas on the table, but be particular about what you want to tackle”.
![[Image: pablo-lectern.DPzf_KbF_Zq2zjj.webp]](https://blog.python.org/_astro/pablo-lectern.DPzf_KbF_Zq2zjj.webp)
Photo by EuroPython (CC BY-NC-SA 4.0)
The issue manifests as seemingly random
Code:
AttributeErrorCode:
jsonCode:
mathCode:
httpCode:
[code]$ cat game.py
import random
if int(input("Pick a number 1-10")) == random.randint(1, 10):
print("You win!")
$ python game.py
AttributeError: module 'random' has no attribute 'randint' (???)
# Why is random.randint() not available???[/code]The issue is usually that a module is “shadowing” the standard library module from a higher-precedence location in
Code:
sys.pathCode:
PYTHONPATHCode:
json.pyCode:
math.pyCode:
[code]$ ls
game.py random.py
# random.py is being imported first, not the stdlib random
$ python game.py
AttributeError: module 'random' has no attribute 'randint'[/code]This issue is caused by Python’s flat module namespace; there is no delineation between what is part of the standard library and what are third-party modules, either dependencies or project code.
Pablo noted that there is a low-cost option that solves this issue, available since Python 3.11: the -P option, which, according to the documentation, “doesn’t prepend a potentially unsafe path to
Code:
sys.pathNew standard library module names are constrained
The problem goes beyond being confusing to users. Pablo explained that the flat namespace means that core developers often need to choose “awkward” names for new modules due to what’s already in use on the Python Package Index (PyPI). This restriction applies even when a module is being adopted from PyPI into the standard library, such as PyYAML, which provides the
Code:
yamlCode:
tomllibCode:
graphlibCode:
zoneinfoCode:
timezoneWhat is one potential solution? Adding a new top-level namespace
for all standard library modules. Pablo suggested the name
Code:
stdfor this namespace, so users who want to guarantee they are importing
a standard library module would
Code:
import std.jsonCode:
from std import jsonPablo assured everyone that
Code:
import jsonCode:
stdwould keep working basically forever (“We can’t break the world, that would be bad”).
Code:
[code]>>> import std.json, json
>>> std.json is json
True
>>> json.__name__
'json' # unchanged[/code]But Pablo didn’t exclude the idea of introducing new modules exclusively
in the
Code:
stdthe new
Code:
stdCode:
[code]>>> import std.new_stdlib_module
# This would work for new modules.
>>> import new_stdlib_module
ImportError
# But new modules without 'std.' wouldn't work...[/code]![[Image: pablo-slide.Dr0ZbgCI_2mABAx.webp]](https://blog.python.org/_astro/pablo-slide.Dr0ZbgCI_2mABAx.webp)
Photo by EuroPython (CC BY-NC-SA 4.0)
Python wouldn’t be alone, either. Many other programming languages have
already namespaced their standard library (or equivalent):
LanguageNamespaceNotesRust/C++
Code:
std::Code:
java.*Code:
"fmt"Code:
node:fsCode:
import osA tempting door opens: unbundling the standard library
Pablo shared that a potential side effect of reserving a new top-level namespace
for the Python standard library is that the standard library
could then more easily be “unbundled”. Unbundling the standard library
would mean that the stdlib modules would be upgradeable separately
from the Python interpreter and independently of each other, likely
distributed through PyPI.
Unbundling the standard library would provide a few benefits:
- Ship standard library modules via PyPI, versioned independently of the interpreter.
- Security fixes out-of-band, not waiting for a Python release.
- Faster iteration on modules that move quicker than Python core.
But there are trade-offs to unbundling, and we know of one concrete example.
Ruby “gemified” its standard library and ran into issues, such as long
deprecation periods (
Code:
requiretransitive dependencies, and a CVE in the
Code:
urilisted in
Code:
GemfileDiscussion
Kushal Das shared that the shadowing issue was a “big problem for newcomers”, especially first-time Python users writing code doing arithmetic in a file named
Code:
math.py![[Image: jukka.Dqbr2b0J_NaBmE.webp]](https://blog.python.org/_astro/jukka.Dqbr2b0J_NaBmE.webp)
Photo by Hugo van Kemenade (CC BY-NC-SA 4.0)
Jukka Lehtosalo shared that he had also “personally encountered this problem”, and asked if there was “data about how often this happens”. Pablo didn’t have concrete data and shared that the error message has improved in recent Python versions.
Pablo didn’t want to over-focus on the shadowing issue and instead wanted to focus on what he believed was the larger issue: how the flat namespace affects how core developers choose standard library module names.
David Hewitt wondered whether there is a “security edge” to this proposal, positing that core developers are “more familiar with what is in the standard library” compared to a beginner, and asked whether this change could help learners know what is included in Python and what isn’t. Pablo pushed back on the security angle: “the standard library is huge, we could do [standard library module] trivia and we’d all fail”. He concluded that this could be another positive reason to adopt the proposal, but he didn’t want to oversell this aspect, either.
Guido van Rossum asked whether every stdlib module would eventually need to move under this proposal, which Pablo confirmed. As a follow-up, Guido asked whether this would mean touching imports across the entire standard library, which Pablo also confirmed, noting that this migration could be “mostly mechanical” and could include freezing all modules.
Peter Bierma asked whether the new
Code:
std![[Image: thomas.DqWCNTa1_Z1hujH2.webp]](https://blog.python.org/_astro/thomas.DqWCNTa1_Z1hujH2.webp)
Photo by Hugo van Kemenade (CC BY-NC-SA 4.0)
Thomas Wouters imagined an incremental rollout of the new
Code:
stdCode:
stdStefan Behnel felt that Python “should provide a way to confidently import from the standard library”. He offered a potential solution that would keep most code the same: limiting the proposal to
Code:
fromCode:
from std import randomCode:
stdCode:
from stdDavid Hewitt noted the precedent already set by the lazy keyword (new in Python 3.15) for changing the
Code:
importAfter a show of hands to get a temperature check on the idea of using a keyword, no one attending “hated the idea” and many attendees “loved the idea”.
Gregory P. Smith provided guidance with his “PEP hat” on, noting that the proposal was potentially trying to solve multiple issues at once. “Keep all the ideas on the table, but be particular about what you want to tackle”.

