The infamous "distutils has already been patched by" error
David
71david at libero.it
Tue Dec 29 07:14:31 EST 2009
I am writing these notes because there is little or no documentation about
this annoying problem.
The error message in subject appears when you try to get the list of
installed modules under the help() enviroment.
>>> help()
help> modules
Please wait a moment while I gather a list of all available modules...
...
AssertionError: distutils has already been patched by <class
py2exe.Distribution at 0x019132D0>
It is caused by monkeypatching of distutils module by other modules,
tipically py2exe.
In detail the cause is this:
0) The help() function is defined by the \python25\lib\site.py module
automatically imported at interpreter startup
1) the standard module \python25\lib\site.py imports the module pydoc and
call the pydoc.help() function (in the class _Helper).
2) The method run() of class ModuleScanner, used by pydoc.help() walks all
installed modules using the pkgutil.walk_packages() function from module
pkgutil, and calls it giving no arguments so the 'onerror' parameter takes
the default value None.
3) The function pkgutil.walk_packages() tries to import each package in a
try/except clause like this:
try:
__import__(name)
except ImportError:
if onerror is not None:
onerror(name)
except Exception:
if onerror is not None:
onerror(name)
else:
raise
As you can see, if onerror is None, the function captures only the
ImportError exception, but...
4) ...when pkgutil.walk_packages() tries to import dist.py module of
setuptools package (\python25\lib\site-packages\setuptools\dist.py)
the following piece of code gets executed...
def _get_unpatched(cls):
"""Protect against re-patching the distutils if reloaded
Also ensures that no other distutils extension monkeypatched the
distutils
first.
"""
while cls.__module__.startswith('setuptools'):
cls, = cls.__bases__
if not cls.__module__.startswith('distutils'):
raise AssertionError(
"distutils has already been patched by %r" % cls
)
return cls
_Distribution = _get_unpatched(_Distribution)
...and, if the py2exe (or other modules) had already been imported and
monkeypatched del setuptools module, the infamous "distutils has already
been patched by" is raised, caputerd by pkgutil.walk_packages() and reraised
because the onerror variable is None.
That said, there are 2 workarounds to avoid this hassle:
A) manually import setuptools module before typing help()
>>> import setuptools
>>> help()
Welcome to Python 2.5! This is the....
help> modules
B) Patch the run() method of pydoc module at line 1862:
for importer, modname, ispkg in
pkgutil.walk_packages(onerror=lambda s:None):
Hope this helps
David.
More information about the Python-list
mailing list