﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
33107	ImportError: partially initialized module '...' has no attribute '...'	Collin Anderson	Mariusz Felisiak	"Today I've been getting some occasional ""ImportError""s when reloading the runserver. I have a feeling it's a race condition when importing my custom auth backend when runserver is reloading, likely caused by #33099 cached imports, committed on Friday. It doesn't happen every time which makes it harder to track down.

Maybe the `cached_import` logic needs to somehow check for a ""partially initialized module"" and use the slow-path in that case?

I'm not 100% it's not just an issue on my end, but I at least wanted to raise this here in case other people have issues and want to diagnose further.

Here's an example (ImportError when importing my custom auth backend):

{{{

Request Method: GET
Request URL: /cart/dropdown/

Django Version: 4.0.dev20210913065016
Python Version: 3.8.10

Template error:
In template templates/order/cart_dropdown.html, error at line 3
   Module ""authbackend"" does not define a ""Bknd"" attribute/class
   3 :  {% if request.order.ops %}


Traceback (most recent call last):
  File ""django/template/base.py"", line 862, in _resolve_lookup
    current = current[bit]

During handling of the above exception ('WSGIRequest' object is not subscriptable), another exception occurred:
  File ""django/utils/module_loading.py"", line 26, in import_string
    return cached_import(module_path, class_name)
  File ""django/utils/module_loading.py"", line 12, in cached_import
    return getattr(modules[module_path], class_name)

The above exception (partially initialized module 'authbackend' has no attribute 'Bknd' (most likely due to a circular import)) was the direct cause of the following exception:
  File ""django/core/handlers/exception.py"", line 47, in inner
    response = get_response(request)
  File ""django/core/handlers/base.py"", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File ""django/shortcuts.py"", line 19, in render
    content = loader.render_to_string(template_name, context, request, using=using)
  File ""django/template/loader.py"", line 62, in render_to_string
    return template.render(context, request)
  File ""django/template/backends/django.py"", line 61, in render
    return self.template.render(context)
  File ""django/template/base.py"", line 176, in render
    return self._render(context)
  File ""django/template/base.py"", line 168, in _render
    return self.nodelist.render(context)
  File ""django/template/base.py"", line 977, in render
    return SafeString(''.join([
  File ""django/template/base.py"", line 978, in <listcomp>
    node.render_annotated(context) for node in self
  File ""django/template/base.py"", line 938, in render_annotated
    return self.render(context)
  File ""django/template/defaulttags.py"", line 386, in render
    return strip_spaces_between_tags(self.nodelist.render(context).strip())
  File ""django/template/base.py"", line 977, in render
    return SafeString(''.join([
  File ""django/template/base.py"", line 978, in <listcomp>
    node.render_annotated(context) for node in self
  File ""django/template/base.py"", line 938, in render_annotated
    return self.render(context)
  File ""django/template/defaulttags.py"", line 288, in render
    match = condition.eval(context)
  File ""django/template/defaulttags.py"", line 829, in eval
    return self.value.resolve(context, ignore_failures=True)
  File ""django/template/base.py"", line 701, in resolve
    obj = self.var.resolve(context)
  File ""django/template/base.py"", line 829, in resolve
    value = self._resolve_lookup(context)
  File ""django/template/base.py"", line 870, in _resolve_lookup
    current = getattr(current, bit)
  File ""order/middleware.py"", line 20, in __get__
    if not request.user.pk:  # if not logged in
  File ""django/utils/functional.py"", line 248, in inner
    self._setup()
  File ""django/utils/functional.py"", line 384, in _setup
    self._wrapped = self._setupfunc()
  File ""django/contrib/auth/middleware.py"", line 25, in <lambda>
    request.user = SimpleLazyObject(lambda: get_user(request))
  File ""django/contrib/auth/middleware.py"", line 11, in get_user
    request._cached_user = auth.get_user(request)
  File ""django/contrib/auth/__init__.py"", line 183, in get_user
    backend = load_backend(backend_path)
  File ""django/contrib/auth/__init__.py"", line 21, in load_backend
    return import_string(path)()
  File ""django/utils/module_loading.py"", line 28, in import_string
    raise ImportError('Module ""%s"" does not define a ""%s"" attribute/class' % (

Exception Type: ImportError at /cart/dropdown/
Exception Value: Module ""authbackend"" does not define a ""Bknd"" attribute/class


}}}
"	Bug	closed	Utilities	4.0	Release blocker	fixed		Keryn Knight	Accepted	1	0	0	0	0	0
