在Pylons应用中创建的工作线程中的日志记录似乎无法工作
我有一个使用pylons框架的应用程序,在某些情况下,我想启动多个工作线程来处理队列中的项目。目前我们还没有使用线程池(理想情况下会用到,但我们会在后面加上)。主要的问题是,工作线程的日志没有写入日志文件。
当我在pylons应用程序外运行代码时,日志记录正常。所以我觉得这可能和pylons的日志处理有关,但不太确定具体是什么问题。
下面是一个简化的代码示例:
import logging
log = logging.getLogger(__name__)
import sys
from Queue import Queue
from threading import Thread, activeCount
def run(input, worker, args = None, simulteneousWorkerLimit = None):
queue = Queue()
threads = []
if args is not None:
if len(args) > 0:
args = list(args)
args = [worker, queue] + args
args = tuple(args)
else:
args = (worker, queue)
# start threads
for i in range(4):
t = Thread(target = __thread, args = args)
t.daemon = True
t.start()
threads.append(t)
# add ThreadTermSignal
inputData = list(input)
inputData.extend([ThreadTermSignal] * 4)
# put in the queue
for data in inputData:
queue.put(data)
# block until all contents are downloaded
queue.join()
log.critical("** A log line that appears fine **")
del queue
for thread in threads:
del thread
del threads
class ThreadTermSignal(object):
pass
def __thread(worker, queue, *args):
try:
while True:
data = queue.get()
if data is ThreadTermSignal:
sys.exit()
try:
log.critical("** I don't appear when run under pylons **")
finally:
queue.task_done()
except SystemExit:
queue.task_done()
pass
请注意,RUN方法中的日志记录会出现在日志文件中,但在工作方法中的日志记录(这是在新线程中运行的)却没有出现。任何帮助都非常感谢。谢谢!
** 编辑:我应该提到,我尝试将“log”变量传递给工作线程,并在线程内重新定义一个新的“log”变量,但都没有成功。
** 编辑:添加了用于pylons应用程序的配置(来自INI文件)。下面的代码片段就是来自INI文件。
[loggers]
keys = root
[handlers]
keys = wsgierrors
[formatters]
keys = generic
[logger_root]
level = WARNING
handlers = wsgierrors
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = WARNING
formatter = generic
[handler_wsgierrors]
class = pylons.log.WSGIErrorsHandler
args = ()
level = WARNING
format = generic
2 个回答
你可以通过参数(args)把一个 log 变量传递给线程。
关于日志记录,有一点需要注意:如果在记录日志时发生了错误(无论是什么原因),这个错误通常会被忽略,不会让应用程序因为日志错误而崩溃。(这取决于使用的处理程序和logging.raiseExceptions
的设置)。所以你可以检查几个方面:
- 确保你的日志信息格式非常简单,可能只用%(message)s,直到你找到问题为止。
- 检查一下Pylons是否关闭了日志记录或者因为某种原因搞乱了处理程序。你没有提供你的日志初始化代码,所以我不确定你使用了什么处理程序等。你可以打印
log.getEffectiveLevel()
来看看日志的详细程度是否被调低了(虽然CRITICAL级别不太可能,但谁知道呢)。
如果你在日志语句旁边加了打印语句,它们的输出是否如你所预期的那样?
更新:我知道关于mod_wsgi和打印的限制,但那只适用于sys.stdout
。你可以例如:
print >> sys.stderr, some_data
或者
print >> open('/tmp/somefile', 'a'), some_data
这样做没有任何问题。
另外,你应该知道,调用logging.config.fileConfig()
(这大概是你描述的配置实现方式)会禁用任何现有的日志记录器,除非它们在配置文件中被明确命名,或者是那些被明确命名的日志记录器的子类。虽然这听起来有点奇怪,但这是因为配置是用来替换现有配置,而不是增加它;而且由于线程可能指向现有的日志记录器,所以它们会被禁用而不是删除。你可以检查一个日志记录器的disabled
属性,看看fileConfig()
是否禁用了这个日志记录器——这可能就是你的问题所在。