Why hasattr gives KeyError?

56 Views Asked by At
chat = await Chat.objects.aget(chatid = chatid)
if hasattr(chat, 'agent') and 'active' in chat.status:
    await asyncio.sleep(5)

This code throws KeyError: 'agent'.

In Python 3 hasattr uses try-except underneath so it shoudn't be a problem if attribute doesn't exist. So what could be possible reasons?

Full traceback:

[ERROR] Exception inside application: You cannot call this from an async context - use a thread or sync_to_async.
Traceback (most recent call last):
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/django/db/models/fields/related_descriptors.py", line 235, in __get__
    rel_obj = self.field.get_cached_value(instance)
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/django/db/models/fields/mixins.py", line 15, in get_cached_value
    return instance._state.fields_cache[cache_name]
KeyError: 'agent'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/channels/routing.py", line 62, in __call__
    return await application(scope, receive, send)
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/channels/security/websocket.py", line 37, in __call__
    return await self.application(scope, receive, send)
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/channels/sessions.py", line 47, in __call__
    return await self.inner(dict(scope, cookies=cookies), receive, send)
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/channels/sessions.py", line 263, in __call__
    return await self.inner(wrapper.scope, receive, wrapper.send)
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/channels/auth.py", line 185, in __call__
    return await super().__call__(scope, receive, send)
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/channels/middleware.py", line 24, in __call__
    return await self.inner(scope, receive, send)
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/channels/routing.py", line 116, in __call__
    return await application(
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/channels/consumer.py", line 94, in app
    return await consumer(scope, receive, send)
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/channels/consumer.py", line 58, in __call__
    await await_many_dispatch(
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/channels/utils.py", line 50, in await_many_dispatch
    await dispatch(result)
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/channels/consumer.py", line 73, in dispatch
    await handler(message)
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/channels/generic/websocket.py", line 194, in websocket_receive
    await self.receive(text_data=message["text"])
  File "/chat/./chat/consumers.py", line 549, in receive
    if hasattr(chat, 'agent') and 'active' in chat.status:
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/django/db/models/fields/related_descriptors.py", line 253, in __get__
    rel_obj = self.get_object(instance)
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/django/db/models/fields/related_descriptors.py", line 216, in get_object
    return qs.get(self.field.get_reverse_related_filter(instance))
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/django/db/models/query.py", line 643, in get
    num = len(clone)
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/django/db/models/query.py", line 380, in __len__
    self._fetch_all()
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/django/db/models/query.py", line 1926, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/django/db/models/query.py", line 91, in __iter__
    results = compiler.execute_sql(
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1560, in execute_sql
    cursor = self.connection.cursor()
  File "/root/.virtualenvs/chat/lib/python3.10/site-packages/django/utils/asyncio.py", line 24, in inner
    raise SynchronousOnlyOperation(message)
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
1

There are 1 best solutions below

1
deceze On

hasattr(object, name)

The arguments are an object and a string. The result is True if the string is the name of one of the object’s attributes, False if not. (This is implemented by calling getattr(object, name) and seeing whether it raises an AttributeError or not.)

https://docs.python.org/3/library/functions.html#hasattr

See the last sentence. The object seems to implement a custom attribute getter, which raises KeyError instead of AttributeError.