Возникает автозагрузка 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 и теперь он снова работает. Я буду продолжать в том же духе, пока они не исправят ошибку.