15

在调试模式下运行 runserver 时, 如何让 Django 1.0 将所有错误写入控制台或日志文件?

我尝试使用带有 process_exception 函数的中间件类,如该问题的接受答案中所述:

你如何在 django 网站上记录服务器错误

某些异常会调用 process_exception 函数(例如:views.py 中的 assert(False)),但不会因为 ImportErrors 等其他错误调用 process_exception(例如:urs.py 中的 import thisclassdoesnotexist)。我是 Django/Python 的新手。这是因为运行时错误和编译时错误之间存在一些区别吗?但是我希望 runserver 会抱怨它是否是编译时错误,而事实并非如此。

我看过 Simon Willison 关于 Django 调试的精彩演示(http://simonwillison.net/2008/May/22/debugging/),但我没有看到适合我的选项。

万一它是相关的,我正在编写一个 Facebook 应用程序,Facebook 用他们自己的消息掩盖 HTTP 500 错误,而不是显示 Django 信息丰富的 500 页面。所以我需要一种将所有类型的错误写入控制台或文件的方法。

编辑:我想我的期望是,当我在 urls.py 中有错误的导入 (ImportError) 时,如果 Django 可以返回一个包含大量详细信息的 500 错误页面,它应该能够将相同的详细信息写入控制台或没有的文件必须在代码中添加任何额外的异常处理。我从未见过围绕 import 语句的异常处理。

谢谢,杰夫

4

5 回答 5

13

有点极端,不过为了调试,可以开启DEBUG_PROPAGATE_EXCEPTIONS设置。这将允许您设置自己的错误处理。设置上述错误处理的最简单方法是覆盖sys.excepthook。这将终止您的应用程序,但它会起作用。您可能可以采取一些措施来使其不会杀死您的应用程序,但这将取决于您为其部署的平台。无论如何,永远不要在生产中使用它!

对于生产,您几乎必须进行广泛的错误处理。我使用的一种技术是这样的:

>>> def log_error(func):
...     def _call_func(*args, **argd):
...         try:
...             func(*args, **argd)
...         except:
...             print "error" #substitute your own error handling
...     return _call_func
...
>>> @log_error
... def foo(a):
...     raise AttributeError
...
>>> foo(1)
error

如果您在视图上使用 log_error 作为装饰器,它将自动处理其中发生的任何错误。

进程_异常函数会为某些异常调用(例如:views.py 中的 assert(False)),但_不会为其他错误(例如 ImportErrors)调用进程异常(例如:在 urs.py 中导入 thisclassdoesnotexist)。我是 Django/Python 的新手。这是因为运行时错误和编译时错误之间存在一些区别吗?

在 Python 中,所有错误都是运行时错误。这导致问题的原因是,在调用视图之前导入模块时,这些错误会立即发生。我发布的第一种方法将捕获此类错误以进行调试。您可能能够为生产解决一些问题,但我认为如果您在生产应用程序中遇到 ImportErrors(并且您没有进行任何动态导入),您会遇到更严重的问题。

不过,像pylint这样的工具可以帮助您消除这些问题。

于 2009-03-27T19:51:37.123 回答
6

某些异常会调用 process_exception 函数(例如:views.py 中的 assert(False)),但不会因为 ImportErrors 等其他错误调用 process_exception(例如:urs.py 中的 import thisclassdoesnotexist)。我是 Django/Python 的新手。这是因为运行时错误和编译时错误之间存在一些区别吗?

不,这只是因为process_exception 中间件仅在视图中引发异常时才被调用

我认为DEBUG_PROPAGATE_EXCEPTIONS(正如 Jason Baker 首先提到的)是你在这里需要的,但我认为你不需要做任何额外的事情(即 sys.excepthook 等),如果你只想将回溯转储到控制台。

如果你想对错误做任何更复杂的事情(即将它转储到文件或数据库),最简单的方法是got_request_exception 信号,Django 为任何与请求相关的异常发送该信号,无论它是否在视图中引发。

django.core.handlers.BaseHandler的get_responsehandle_uncaught_exception方法是该领域的指导性(和简短)阅读。

无需向代码添加任何额外的异常处理。我从未见过围绕 import 语句的异常处理。

再看看周围,你会看到它完成了(通常在你想以某种特定方式处理缺少依赖的情况下)。也就是说,如果您必须在整个代码中添加额外的 try-except 块以对异常处理方式进行全局更改,那当然会非常难看!

于 2009-03-30T04:53:02.687 回答
2

首先,通过异常日志可以看到的编译时错误非常少。如果你的 Python 代码没有有效的语法,它会在日志被打开写入之前很久就死掉了。

在 Django 运行服务器模式下,“打印”语句写入标准输出,您可以看到。然而,这不是一个好的长期解决方案,所以不要指望它。

但是,当 Django 在 Apache 下运行时,这取决于您使用的是哪个插件。mod_python 不容易处理。可以强制 mod_wsgi 将 stdout 和 stderr 发送到日志文件。

但是,您最好的选择是日志记录模块。将初始化放入顶层urls.py以配置日志记录。(或者,也许,你的settings.py

确保每个模块都有一个可用于写入日志消息的记录器。

确保您进行的每个 Web 服务调用都有一个 try/except 块,并将异常写入日志。

于 2009-03-27T18:51:16.193 回答
1

http://groups.google.com/group/django-nashville/browse_thread/thread/b4a258250cfa285a?pli=1

于 2009-11-13T05:24:22.497 回答
-1

如果你在 *nix 系统上,你可以

在 python 中写入日志(例如 mylog.txt),然后在控制台中运行“tail -f mylog.txt”

这是一种近乎实时查看任何类型日志的便捷方式

于 2009-03-28T22:03:55.627 回答