Каждый раз, когда мой код достигает определенной строки, он, кажется, вызывает ошибку dictionary update sequence element #0 has length X; 2 is required.
Значение X может измениться, но при вызове этого почти всегда возникает ошибка:
if request.user.is_authenticated
Это python 3.6.7, django 2.1.7
Вот стек ошибок
Traceback:
File "/path/to/venv/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
34. response = get_response(request)
File "/path/to/venv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
126. response = self.process_exception_by_middleware(e, request)
File "/path/to/venv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
124. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "./playerdata/api/tokens.py" in token_queries
87. if request.user.is_authenticated:
File "/path/to/venv/lib/python3.6/site-packages/django/utils/functional.py" in inner
213. self._setup()
File "/path/to/venv/lib/python3.6/site-packages/django/utils/functional.py" in _setup
347. self._wrapped = self._setupfunc()
File "/path/to/venv/lib/python3.6/site-packages/django/contrib/auth/middleware.py" in <lambda>
24. request.user = SimpleLazyObject(lambda: get_user(request))
File "/path/to/venv/lib/python3.6/site-packages/django/contrib/auth/middleware.py" in get_user
12. request._cached_user = auth.get_user(request)
File "/path/to/venv/lib/python3.6/site-packages/django/contrib/auth/__init__.py" in get_user
189. user = backend.get_user(user_id)
File "/path/to/venv/lib/python3.6/site-packages/django/contrib/auth/backends.py" in get_user
98. user = UserModel._default_manager.get(pk=user_id)
File "/path/to/venv/lib/python3.6/site-packages/django/db/models/manager.py" in manager_method
82. return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/path/to/venv/lib/python3.6/site-packages/django/db/models/query.py" in get
390. clone = self.filter(*args, **kwargs)
File "/path/to/venv/lib/python3.6/site-packages/django/db/models/query.py" in filter
844. return self._filter_or_exclude(False, *args, **kwargs)
File "/path/to/venv/lib/python3.6/site-packages/django/db/models/query.py" in _filter_or_exclude
862. clone.query.add_q(Q(*args, **kwargs))
File "/path/to/venv/lib/python3.6/site-packages/django/db/models/sql/query.py" in add_q
1263. clause, _ = self._add_q(q_object, self.used_aliases)
File "/path/to/venv/lib/python3.6/site-packages/django/db/models/sql/query.py" in _add_q
1289. joinpromoter.add_votes(needed_inner)
File "/path/to/venv/lib/python3.6/site-packages/django/db/models/sql/query.py" in add_votes
2171. self.votes.update(votes)
File "/usr/lib/python3.6/collections/__init__.py" in update
620. super(Counter, self).update(iterable) # fast path when counter is empty
Exception Type: ValueError
Exception Value: dictionary update sequence element #0 has length 9; 2 is required
Код вокруг request.user.is_authenticated:
def token_queries(request):
data = None
if request.user.is_authenticated:
data = login_required(request)
if data is None:
data = anonymous(request)
return json_response(data)
Обновлено: Дополнительная информация
Я должен уточнить, что эта ошибка срабатывает один раз в день, ближе к пику моей активности на сайте. Как только он сработает, он будет продолжать спамить в течение нескольких часов, прежде чем остановится. Это также происходит не только в файле tokens,py, но и почти везде в коде, где пользователь пытается получить доступ.
ОБНОВЛЕНИЕ: что-то связанное с балансировкой нагрузки
Ошибка, похоже, связана с балансировки нагрузки. Когда ошибка начинает спамить, это происходит только на одном узле LB за раз. Я обнаружил, что удаление узла из моего балансировщика нагрузки предотвратит это. Это даже не обязательно должен быть узел, на котором происходит ошибка.! Если я снова включу оба узла, ошибка сразу же начнет срабатывать снова.
Например:
Единственный способ остановить это — перезапустить машину, на которой размещен узел, на котором произошла ошибка.
Добавление липкости на 1 час к LB не решило проблему.
Я запускаю Django через Nginx на сервере AWS.
@dirkgroten добавил код. Эта ошибка возникает почти во всех местах, где я пытаюсь получить пользователя.
Как определена ваша пользовательская модель? Каково значение AUTH_USER_MODEL в ваших настройках?
Я использую AUTH_USER_MODEL по умолчанию (никогда не менял значение)
Что вы используете для своих занятий? django.contrib.sessions.middleware.SessionMiddleware по умолчанию? И SESSION_BACKEND по умолчанию? Можете ли вы установить точку останова перед if request.user... и напечатать request.session['_auth_user_id']
Использование django.contrib.sessions.middleware.SessionMiddleware и никаких изменений не было сделано один SESSION_BACKEND. К сожалению, эта ошибка возникает только в рабочей среде, и я не могу воспроизвести ее локально, чтобы использовать точку останова. Он также будет нормально работать в течение нескольких дней подряд, но затем внезапно сработает и будет спамить ошибку в течение нескольких часов, прежде чем, наконец, остановится...
Глядя на код Django, я думаю, что эта ошибка может быть вызвана, если что-то не так в вашем сеансе. Возможно, поврежденная запись в таблице сеансов. Возможно, вы захотите очистить сеансы с истекшим сроком действия (если у вас нет задания cron, которое уже делает это регулярно), а затем непосредственно взглянуть на таблицу сеансов базы данных в рабочей среде, чтобы увидеть, сможете ли вы обнаружить поврежденную строку.
На самом деле вы должны добавить попытку, кроме как сейчас, вокруг вашего ошибочного оператора, чтобы напечатать дополнительную информацию в журналах при возникновении исключения. Например, зарегистрируйте файл cookie сеанса запроса, чтобы позже вы могли получить этот сеанс в рабочей оболочке.
Что заставляет вас думать, что это происходит из-за поврежденных записей сеансов? На самом деле, у меня раньше эта ошибка также вызывалась другой, говорящей 'SessionStore' object has no attribute '_session_cache', так что вы можете что-то понять.
@dirkgroten попробовал какое-то сложное решение и удалил все сеансы в django_session.... К сожалению, ошибка все еще рассылает спам.
Что заставило меня подумать, что это как-то связано с сеансами, так это то, что я думаю, что способ получить вашу ошибку, если user_id, который извлекается из сеанса, не является целым числом. Я думаю, что добавление некоторых конкретных журналов — единственный способ получить больше информации. Постарайтесь записать как можно больше информации при возникновении ошибки.
Это не проблема, связанная с вашей моделью пользователя, но я думаю, что в вашем urls.py. Покажите нам URL-адрес приложения
@Wariored Что ты имеешь в виду? Если возможно, я хотел бы показать больше кода, только если это действительно необходимо. Приложение будет работать нормально в 90% случаев, но примерно раз в 2 дня ошибка, о которой я говорю, начнет безостановочно рассылать спам в течение нескольких часов подряд.
Не могли бы вы поделиться url.py, который указывает на функцию token_queires?
Какое промежуточное ПО сеанса и серверную часть аутентификации вы используете?
@sun_jara, в файле URL нет ничего особенного. Какую проблему вы ищете?
@DevangPadhiyar 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware' и в настройках: SESSION_ENGINE = "django.contrib.sessions.backends.cached_db". Я также использую фреймворк django rest.
Любое пользовательское промежуточное ПО?
@Trent нет пользовательских промежуточных программ :(
Судя по строке user = UserModel._default_manager.get(pk=user_id) в стеке ошибок, я думаю, что что-то не так с вашим ответом на запрос к базе данных. Это также объясняет, почему это происходит только на производстве. Какую базу данных SQL вы используете?
Я сомневаюсь, что это как-то связано с сеансами, промежуточным программным обеспечением или базой данных. Проблема возникает во время построения запроса UserModel._default_manager.get(pk=user_id) при определении того, какой тип JOIN следует использовать.
@gdlmx Я использую MySQL с INNODB
@RyanPergent абсолютно одинаковы, давайте помогать друг другу и публиковать все версии программного обеспечения: nginx 1.19.2 gunicorn==20.0.4 django "==3.0.9 python3.6 pipenv, docker Gunicorn начинается со следующей строки (это может быть важно) : gunicorn conf.wsgi:application --bind 0.0.0.0:8000 --workers 5 --worker-connections=1000
@IvanBorshchov Stack Overflow также требует, чтобы в вопросе было достаточно информации, чтобы можно было воспроизвести проблему. Наш формат не предназначен для того, чтобы просто гадать, почему что-то происходит. Судя по описанию проблемы, это также тесно связано с проблемой конфигурации производственной системы, а не с проблемой программирования, что делает ее неактуальной здесь, в Stack Overflow. Может быть программное решение проблемы, но если это так, то в вопросе необходимо указать минимальный воспроизводимый пример, который фактически разрешает дублирование проблемы.
Эта ошибка возникает довольно глубоко в ORM; логика add_votes определяет, следует ли использовать LOUTER JOIN вместо INNER. Не могли бы вы предоставить более подробную информацию о том, какой сервер WSGI вы используете. Это случайно не mod_wsgi Apache? Кроме того, у вас есть кастомный AUTH_USER_MODEL, который делает что-то странное с его базовым менеджером?
@Makyen Главный вопрос этого вопроса - КАК создать шаги для воспроизведения, это происходит очень часто. Такие проблемы очень редки, т.к. случаются после месяца производственной работы. И воспроизвести их абсолютно сложно. Жаль, что вопрос закрыли. Это могло бы спасти многих людей и развить отрасль в целом. Невозможность воспроизвести просто откладывает проблему и делает следующий фреймворк непригодным для использования






Возможно, проверьте, чтобы настройка СЕКРЕТНЫЙ КЛЮЧ была одинаковой на каждом из ваших узлов.
Просто догадка, основанная на вашей балансировке нагрузки и комментариях к сеансу.
Оба узла имеют одинаковый код (синхронизированный репозиторий). Если бы секретный ключ был неправильным, ошибка происходила бы постоянно, а не периодически, верно?
Согласитесь, выглядит довольно странно, у меня такая же проблема, секретный ключ стабилен
Я могу определить ненормальную строку в вашей трассировке ошибок:
File "/usr/lib/python3.6/collections/__init__.py" in update 620. super(Counter, self).update(iterable) # fast path when counter is empty
В нормальных условиях эта линия никогда не должна быть достигнута. Если вы посмотрите на исходный код в "collections/__init__.py",
if isinstance(iterable, Mapping):
...
super(Counter, self).update(iterable) # fast path when counter is empty
Переменная iterable была передана от переменной needed_inner
в функции _add_q. Его тип всегда должен быть <class 'set'>. Поэтому isinstance(iterable, Mapping) никогда не должно быть True.
Как вы сказали, вы не использовали пользовательский AUTH_USER_MODEL. Таким образом, наиболее правдоподобным объяснением является скрытая ошибка в реализации Python Nginx WSGI (возможно, связанная с балансировкой нагрузки).
Покажите нам код
def token_queries()в токены.py в строке 87.