在django应用程序中启动线程时出现奇怪的错误

时间:2012-03-17 12:10:24

标签: python django multithreading apache mod-wsgi

我正在尝试从django进程执行简单的网络作业(ping)。 Django是通过apache的mod_wsgi部署的。但代码仅在首次运行时有效,在后续运行时返回以下错误。

Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/var/www/propingui/ping/views.py" in ping
  32.             p = Pool(len(fls))
File "/usr/lib/python2.7/multiprocessing/pool.py" in __init__
  674.         Pool.__init__(self, processes, initializer, initargs)
File "/usr/lib/python2.7/multiprocessing/pool.py" in __init__
  134.         self._repopulate_pool()
File "/usr/lib/python2.7/multiprocessing/pool.py" in _repopulate_pool
  197.             w.start()
File "/usr/lib/python2.7/multiprocessing/dummy/__init__.py" in start
  73.         self._parent._children[self] = None

Exception Type: AttributeError at /
Exception Value: '_DummyThread' object has no attribute '_children'

代码如下:

from multiprocessing.pool import ThreadPool as Pool

...

def _ping((host, firing_location)):
    pinger = Pyro4.Proxy("PYRONAME:" + firing_location)
    return pinger.ping(host)

def ping(request):
    if request.method == 'POST':
        form = PingForm(request.POST)
        if form.is_valid():
            host = form.cleaned_data['host']
            fls = ['g1','a1']
            p = Pool(len(fls))
            noanswer = False
            try: 
                jobs = p.map(_ping, zip([host]*len(fls), fls) )
            except:
                jobs = []
            ...
            return ...

我试图谷歌错误但没有发现任何东西,我不明白问题的确切来源。有趣的是,如果我将ThreadPool更改为多处理池,一切正常。我认为这是由于在django中产生线程的问题而引起的。

3 个答案:

答案 0 :(得分:5)

当在threading.Thread中使用ThreadPool时,很可能发生known Python bug

此问题有no good solution,只是在您想要使用ThreadPool的线程中调用以下内容的解决方法:

if not hasattr(threading.current_thread(), "_children"):
    threading.current_thread()._children = weakref.WeakKeyDictionary()

答案 1 :(得分:1)

我认为这是因为mod_wsgi。在wsgi应用程序中生成线程或分叉不是一个好主意,因为它可能会干扰Web服务器为应用程序生成工作者的方式。

也许你可以创建一个pyro服务,将你的ping命令发送到所有服务器......

答案 2 :(得分:1)

使用线程,我有同样的问题,最终放弃并使用线程模块而不是ThreadPool现在一切正常,所以我认为问题必须是ThreadPool而不是Python线程所有

您可以实施自己的ThreadPool或重复其他人所做的事情(例如thisthis