Python 3.13: ModuleNotFoundError: No module named 'distutils' + some packages crash with ssl.wrap_socket
Upgraded a project to Python 3.13 and now installs/runtime are messy.
I’m seeing two kinds of failures depending on what I try to install/import:
- ModuleNotFoundError: No module named 'distutils'
- AttributeError: module 'ssl' has no attribute 'wrap_socket'
This used to work on 3.11. I’m on a clean machine now, created a new virtual environment, then installed requirements (some of them are older and I can’t replace all immediately).
What’s the pragmatic way to get this running on 3.13? I’m fine with “update toolchain / recreate venv / pin Python”, but I want to understand what’s actually going on and what the correct fix path is.
Answers
Nina Klein
(Edited)
Don’t try to “pip install distutils”. That’s the wrong direction.
Martin Hoffmann
(Edited)
The ssl.wrap_socket part is a separate issue: some older libraries call ssl.wrap_socket(...) directly. That API is removed in Python 3.12+, so you get AttributeError.
The fix is usually one of these:
The important point is: the “context” owns the TLS configuration now; you don’t wrap raw sockets via a top-level helper.
If you can’t update the dependency and it hard-codes ssl.wrap_socket, Python 3.11 is the realistic short-term workaround. Monkey-patching ssl is possible but brittle and not something you want in production.
Hannah Müller
(Edited)
+1 on “update the library”. I’ve seen this with older DB connectors and some HTTP clients. Once updated, the wrap_socket error just disappears.
Stefan Wagner
(Edited)
The ssl.wrap_socket error came from a different old dependency. Updating it fixed the issue; it now uses the context-based wrapping internally.
So the final state is: updated a couple of packages + pinned one remaining problematic package to a newer major. No local hacks.
Katrin Becker
(Edited)
Recreate the venv after upgrading pip/setuptools/wheel. Don’t reuse the old one.
Julia Schneider
(Edited)
distutils is gone starting with Python 3.12. It’s not “missing from your venv”, it’s removed from the standard library. So any package that still does import distutils... will break on 3.12/3.13.
The most reliable fix path is:
1. Make sure your packaging toolchain is current for 3.13
On a “fresh” 3.13 install, you can still end up with an old pip/setuptools in a venv (or no usable pip if the bootstrap went sideways). Use Python’s built-in bootstrap to install/refresh pip for that interpreter, then upgrade pip, setuptools, and wheel inside the venv.
(Don’t overthink it: if pip is old, it will happily pull sdists and run setup logic that assumes distutils exists.)
2. Recreate the virtual environment after you fix pip
People skip this and keep chasing ghosts. If the venv was created while your toolchain was inconsistent, rebuilding it is faster than patching it.
3. If a dependency still imports distutils, you don’t “install distutils”
The options are:
In short: upgrade packaging tools first; then either update the offending library or downgrade Python. There isn’t a supported “bring distutils back” route on 3.13.
Felix Neumann
(Edited)
One extra symptom: even if your code doesn’t use distutils, an old build backend can pull in legacy setup logic and fail at build time. Upgrading the packaging stack first avoids a lot of noise.
Tobias Schmidt
(Edited)
This is what we did. 3.13 is nice, but not worth fighting one abandoned dependency.
Stefan Wagner
(Edited)
Confirmed: one dependency still imports distutils during install. I first tried to “fix” it by adding random system packages, wasted an hour.
What worked:
After that, the distutils error is gone.
Daniel Fischer
(Edited)
If you must run it today: pin Python to 3.11. distutils removal is not something you fix in your app.