django 无法读取的 Post 错误:请求数据读取错误

24 投票
3 回答
14235 浏览
提问于 2025-04-17 19:51

我正在做一个django项目,收到了这个错误邮件。

错误追踪信息

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

这个错误为什么会发生呢?
怎么解决这个问题?

3 个回答

0

我写了一个限制频率的版本。你会想要查看错误信息,如果它频繁出现的话,但如果每五分钟才出现一次,那你就可以忽略它。这个假设是,如果在一分钟内出现了两次错误,那你可能需要检查一下是否有什么问题。

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"],
        },
16

在大型应用中,你总会遇到偶尔被取消的请求。如果你收到500封邮件,这可真让人烦。

我不建议完全忽视这些邮件。如果你收到的UnreadablePostErrors(无法读取的帖子错误)很多,那就说明出现了问题,比如响应时间太长导致用户取消了请求。

我的解决办法是为管理员邮件设置一个自定义过滤器,这样你可以添加任何你想要的逻辑。

最简单的做法可能是随机忽略20个UnreadablePostErrors中的19个。这样,如果真的出问题,我还是会收到通知,但我会少收到20倍的邮件。

如果你想要更复杂的解决方案,可以参考@pztrick的做法。

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:

'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'
     },

     ...
19

为什么会出现这个错误呢?

因为服务器收到了一个格式不正确的请求,这种情况可能有很多原因。比如,有人可能在加载页面的时候取消了,或者有人网络不好,连接中断了,甚至可能是宇宙射线把某个数据位翻转了

其实你不需要太担心这个问题,除非它频繁发生。你可以记下这些错误出现的情况,看看是不是总是在同一个页面上出现。

怎么解决呢?

目前你是无法解决的。至少在现在这个阶段,先收集更多关于这个错误发生时的数据。看看能不能找到一种方法手动触发这个错误。

撰写回答