Возникает автозагрузка Django: TypeError: unhashable type: 'types.SimpleNamespace'

Когда я обновляю importlib_meta с версии 8.4.0 до 8.5.0 (выпущенной только вчера, 11 сентября 2024 года), я получаю следующую ошибку при запуске сервера разработки с python manage.py runserver:

   File "/app/manage.py", line 17, in main
     execute_from_command_line(sys.argv)
   File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
     utility.execute()
   File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 436, in execute
     self.fetch_command(subcommand).run_from_argv(self.argv)
   File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 413, in run_from_argv
     self.execute(*args, **cmd_options)
   File "/usr/local/lib/python3.10/site-packages/django/core/management/commands/runserver.py", line 75, in execute
     super().execute(*args, **options)
   File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 459, in execute
     output = self.handle(*args, **options)
   File "/usr/local/lib/python3.10/site-packages/django/core/management/commands/runserver.py", line 112, in handle
     self.run(**options)
   File "/usr/local/lib/python3.10/site-packages/django/core/management/commands/runserver.py", line 119, in run
     autoreload.run_with_reloader(self.inner_run, **options)
   File "/usr/local/lib/python3.10/site-packages/django/utils/autoreload.py", line 671, in run_with_reloader
     start_django(reloader, main_func, *args, **kwargs)
   File "/usr/local/lib/python3.10/site-packages/django/utils/autoreload.py", line 660, in start_django
     reloader.run(django_main_thread)
   File "/usr/local/lib/python3.10/site-packages/django/utils/autoreload.py", line 344, in run
     self.run_loop()
   File "/usr/local/lib/python3.10/site-packages/django/utils/autoreload.py", line 350, in run_loop
     next(ticker)
   File "/usr/local/lib/python3.10/site-packages/django/utils/autoreload.py", line 390, in tick
     for filepath, mtime in self.snapshot_files():
   File "/usr/local/lib/python3.10/site-packages/django/utils/autoreload.py", line 411, in snapshot_files
     for file in self.watched_files():
   File "/usr/local/lib/python3.10/site-packages/django/utils/autoreload.py", line 304, in watched_files
     yield from iter_all_python_module_files()
   File "/usr/local/lib/python3.10/site-packages/django/utils/autoreload.py", line 120, in iter_all_python_module_files
     return iter_modules_and_files(modules, frozenset(_error_files))
 TypeError: unhashable type: 'types.SimpleNamespace'

Я действительно смог свести проблему к следующему коммиту https://github.com/python/importlib_metadata/commit/56b61b3dd90df2dba2da445a8386029b54fdebf3.

Когда я устанавливаю importlib_meta за один коммит до проблемного коммита через pip install git+https://github.com/python/importlib_metadata@d968f6270d55f27a10491344a22e9e0fd77b5583, ошибка исчезает. Когда я устанавливаю importlib_meta на проблемный коммит, ошибка начинает появляться.

Я не могу понять, что такое Traceback и как проблема может быть связана с изменениями в упомянутом коммите. Есть ли у кого-нибудь идеи, что может вызвать эту проблему или как я могу ее отладить?

Проблемная фиксация в в importlib_meta помещает объект types.SimpleNamespace в sys.modules["zipp.compat.overlay.zipfile"]:

zipfile = types.SimpleNamespace(**vars(importlib.import_module('zipfile')))
...
sys.modules[__name__ + '.zipfile'] = zipfile  # type: ignore[assignment]

Вот сайт с ошибками при вызове в django:

    modules = tuple(
        m
        for m in map(sys.modules.__getitem__, keys)
        if not isinstance(m, weakref.ProxyTypes)
    )
    # WARNING: `modules` now has `zipfile = types.SimpleNamespace(...)` in it
    return iter_modules_and_files(modules, frozenset(_error_files))


@lru_cache(maxsize=1)
def iter_modules_and_files(modules, extra_files):

Из документации по Python на @functools.lru_cache:

Поскольку для кэширования результатов используется словарь, позиционные и ключевые аргументы функции должны быть хэшируемыми.

types.SimpleNamespace() не является хэшируемым:

>>> from types import SimpleNamespace
>>> hash(SimpleNamespace())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'types.SimpleNamespace'

Я бы сказал, что это проблема django - django должен учитывать тот факт, что sys.modules подвергается monkeypatching во время выполнения и может содержать произвольные объекты (включая нехешируемые).

Я просто жестко закодировал

importlib_metadata==8.4.0

в мой файл requirements.txt и теперь он снова работает. Я буду продолжать в том же духе, пока они не исправят ошибку.

Вернуться на верх