关于python:Django UndefinedPostError:请求数据读取错误

django UnreadablePostError: request data read error

我正在处理Django项目,但收到此错误电子邮件。

堆栈跟踪

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
File"/usr/local/lib/python2.7/dist-packages/Django-1.4.3-py2.7.egg/django/core/handlers/wsgi.py", line 180, in _get_post
    self._load_post_and_files()

File"/usr/local/lib/python2.7/dist-packages/Django-1.4.3-py2.7.egg/django/http/__init__.py", line 379, in _load_post_and_files
    self._post, self._files = QueryDict(self.body, encoding=self._encoding), MultiValueDict()

File"/usr/local/lib/python2.7/dist-packages/Django-1.4.3-py2.7.egg/django/http/__init__.py", line 335, in body
    self._body = self.read()

File"/usr/local/lib/python2.7/dist-packages/Django-1.4.3-py2.7.egg/django/http/__init__.py", line 391, in read
    return self._stream.read(*args, **kwargs)

File"/usr/local/lib/python2.7/dist-packages/Django-1.4.3-py2.7.egg/django/core/handlers/wsgi.py", line 98, in read
    result = self.buffer + self._read_limited()

File"/usr/local/lib/python2.7/dist-packages/Django-1.4.3-py2.7.egg/django/core/handlers/wsgi.py", line 92, in _read_limited
    result = self.stream.read(size)

UnreadablePostError: request data read error

为什么会发生此错误?
如何解决?


Why this error is happening ?

因为服务器正在接收格式错误的请求,这可能由于多种原因而发生。某人可能已取消加载页面,某人可能断开了糟糕的互联网连接,宇宙射线可能已经翻转了一点。

这不是您真正需要担心的事情,直到它开始非常频繁地发生。您可能想在发生这些错误时进行记录,然后查看是否在同一页面上。

How to solve?

你不能。至少目前还没有。收集有关此错误确切发生时间的更多数据。查看是否可以找到手动触发它的方法。


有了大规模的应用程序,您总是会收到偶尔被取消的请求。如果您收到500封电子邮件,它们可能会非常乏味。

我不建议完全忽略它们。如果涌现出UndefinedPostErrors,则表示出现了错误,例如较长的响应时间会导致用户取消请求。

我的解决方案是为管理员电子邮件定制过滤器,您可以在其中放置所需的任何逻辑。

最简单的方法可能是随机忽略20个UndefinedPostErrors中的19个。这样,如果出现问题,我仍会得到通知,但我的受害时间会减少20倍。

如果您想要更精美的东西,我会去@pztrick的解决方案。

1
2
3
4
5
6
7
8
9
10
11
import logging
import random
from django.http import UnreadablePostError

class ReduceUnreadablePostErrors(logging.Filter):
    def filter(self, record):
        if record.exc_info:
            exc_value = record.exc_info[1]
            if isinstance(exc_value, UnreadablePostError):
                return random.randint(1,20) % 20==0
        return True

settings.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
'filters': {
   'reduce_unreadable_post_errors' : {
        '()' : 'path.to.your.ReduceUnreadablePostErrors'
    },

    ...

'handlers': {
    'mail_admins': {
        'level': 'ERROR',
        'filters': ['require_debug_false','reduce_unreadable_post_errors'],
        'class': 'common.utils.log.AdminEmailHandlerWithEmail'
     },

     ...


我为此写了节制版。如果出现尖峰,您将希望看到该错误,但是如果每隔五分钟出现一次,则可以忽略它。假定如果在一分钟内两次出现该错误,则可能会遇到一些问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def skip_unreadable_post(record):
    if record.exc_info:
        exc_value = record.exc_info[1]
        if isinstance(exc_value, UnreadablePostError):
            cache_key ="settings.unreadable_post_error"
            r = make_redis_interface("CACHE")
            if r.get(cache_key) is not None:
                # We've seen this recently; let it through; hitting it a lot
                # might mean something.
                return True
            else:
                # Haven't seen this recently; cache it with a minute expiry,
                # and don't let it through.
                r.set(cache_key,"True", ex=60)
                return False
    return True

...
   "filters": {
       "skip_unreadable_posts": {
           "()":"django.utils.log.CallbackFilter",
           "callback": skip_unreadable_post,
        },
    },
...
       "django.server": {
           "level":"INFO",
           "class":"logging.StreamHandler",
           "formatter":"django.server",
           "filters": ["skip_unreadable_posts"],
        },