How to get time.strptime()?

Ian Kelly ian.g.kelly at gmail.com
Thu Dec 27 21:47:29 EST 2012


On Thu, Dec 27, 2012 at 5:33 PM, Gnarlodious <gnarlodious at gmail.com> wrote:
> Graham Dumpleton has informed me that the the relevant bug reports are:
>
> http://bugs.python.org/issue8098
> http://bugs.python.org/issue9260
>
> To quote:
>
> All the problems derive from a stupid function in Python internals called PyImport_ImportModuleNoBlock(). It was designed to avoid lockups of the import machinery but just causes other problems because a module import can fail if the import lock is held by a different thread. This faulty magic fairy dust was sprinkled on the time.strptime() function which internally loads _strptime module. If you access time.strptime() when another thread holds the import lock, the call will fail because of a failed import.
>
> So there. As more people update to Python 3.3.0 hopefully this magic fairy dust workaround will see some daylight.

Thanks for the context, but that actually seems to be describing the
situation from Python 3.2.  Python 3.3 introduced module-level import
locking with improved deadlock detection that looks for actual cycles
and is supposed to fix the unnecessary ImportErrors described in
#8098, rendering the PyImport_ImportModuleNoBlock "fairy dust"
unnecessary -- in 3.3, I understand that PyImport_ImportModuleNoBlock
is now just a synonym for PyImport_ImportModule.  But you're reporting
that you're still seeing issues with this in Python 3.3.  Diving into
the code, I think I start to understand why.  Take a look at this
function from Lib/importlib/_bootstrap.py:

def _lock_unlock_module(name):
    """Release the global import lock, and acquires then release the
    module lock for a given module name.
    This is used to ensure a module is completely initialized, in the
    event it is being imported by another thread.

    Should only be called with the import lock taken."""
    lock = _get_module_lock(name)
    _imp.release_lock()
    try:
        lock.acquire()
    except _DeadlockError:
        # Concurrent circular import, we'll accept a partially initialized
        # module object.
        pass
    else:
        lock.release()


Normally, it just acquires and releases the module lock to ensure that
the module has been completely initialized.  If a deadlock is
detected, however, then it skips that step and instead of raising an
ImportError (which would seem to me to be the right thing to do here)
it allows the importing code to simply proceed with a module that may
not be fully imported yet.  Since your error message concerned missing
module-level attributes within the _strptime module, that seems to be
what you're running into.  The time.strptime function attempts to
import _strptime, which is already being imported by another thread;
for some unknown reason it detects a cyclical deadlock as a result of
this; it then white-washes the deadlock and tries to use the _strptime
module anyway, causing a different error to occur.  The question then
is how you're managing to get an import cycle by using strptime.



More information about the Python-list mailing list