CherryPy服务器使用线程来处理请求。在我的线程服务器中,有一种方法非常复杂,CPU很重,所以我不得不从方法请求线程内部使用多处理来并行执行。
我想我应该换掉
class Server(object)
@cherrypy.expose
def expensive_method(self):
...
x = map(fnc, args)
...
def fnc(args):
# this method doesn't need CherryPy but is expensive to compute
...
cherrypy.quickstart(Server())(效果很好)
def expensive_method(self):
pool = Pool()
x = pool.map(fnc, args)
pool.terminate()但这不管用。即使在更简单的情况下,当我根本不使用泳池的时候,
def expensive_method(self):
pool = Pool()
x = map(fnc, args) # <== no pool here! same as the working example
pool.terminate()我得到了一个例外
[08/Jan/2013:20:05:33] ENGINE Caught signal SIGTERM.
2013-01-08 20:05:33,919 : INFO : _cplogging:201 : error(CP Server Thread-3) : [08/Jan/2013:20:05:33] ENGINE Caught signal SIGTERM.
[08/Jan/2013:20:05:33] ENGINE Bus STOPPING
2013-01-08 20:05:33,920 : INFO : _cplogging:201 : error(CP Server Thread-3) : [08/Jan/2013:20:05:33] ENGINE Bus STOPPING
[08/Jan/2013:20:05:38] ENGINE Error in 'stop' listener <bound method Server.stop of <cherrypy._cpserver.Server object at 0x1090c3c90>>
Traceback (most recent call last):
File "/Volumes/work/workspace/vew/prj/lib/python2.7/site-packages/cherrypy/process/wspbus.py", line 197, in publish
output.append(listener(*args, **kwargs))
File "/Volumes/work/workspace/vew/prj/lib/python2.7/site-packages/cherrypy/process/servers.py", line 223, in stop
wait_for_free_port(*self.bind_addr)
File "/Volumes/work/workspace/vew/prj/lib/python2.7/site-packages/cherrypy/process/servers.py", line 410, in wait_for_free_port
raise IOError("Port %r not free on %r" % (port, host))
IOError: Port 8888 not free on '127.0.0.1'我认为这种情况发生在请求的末尾,无论是在pool.terminate()之后还是在期间。
分叉工作进程不会对服务器或端口进行任何操作。有没有办法告诉CherryPy和/或多进程忽略“服务器位”?我在fnc中不需要任何端口或套接字。
我需要使用Python2.7.1和CherryPy 3.2.2在OSX + Linux上工作。
进展1:
按照西尔万的建议,我尝试了pool = Pool(initializer=cherrypy.server.unsubscribe)。没有例外,一切正常,但我在日志中看到
[08/Jan/2013:21:16:35] ENGINE Caught signal SIGTERM.
2013-01-08 21:16:35,908 : INFO : _cplogging:201 : error(CP Server Thread-10) : [08/Jan/2013:21:16:35] ENGINE Caught signal SIGTERM.
[08/Jan/2013:21:16:35] ENGINE Bus STOPPING
2013-01-08 21:16:35,909 : INFO : _cplogging:201 : error(CP Server Thread-10) : [08/Jan/2013:21:16:35] ENGINE Bus STOPPING
[08/Jan/2013:21:16:35] ENGINE Bus STOPPED
2013-01-08 21:16:35,909 : INFO : _cplogging:201 : error(CP Server Thread-10) : [08/Jan/2013:21:16:35] ENGINE Bus STOPPED
[08/Jan/2013:21:16:35] ENGINE Bus EXITING
2013-01-08 21:16:35,909 : INFO : _cplogging:201 : error(CP Server Thread-10) : [08/Jan/2013:21:16:35] ENGINE Bus EXITING
[08/Jan/2013:21:16:35] ENGINE Bus EXITED
2013-01-08 21:16:35,910 : INFO : _cplogging:201 : error(CP Server Thread-10) : [08/Jan/2013:21:16:35] ENGINE Bus EXITED这样行吗?这是否会带来任何麻烦(例如,在不同线程中同时处理多个请求时)?
进展2:
实际上,上面的这些程序偶尔会留下空闲的进程:(因此它不能正常工作。奇怪的是,这些空闲进程是由Pool生成的,所以它们应该是守护进程,但实际上它们甚至在杀死父进程之后仍然存活。
进展3:
我将分叉(=Pool()调用)移到请求处理方法之外,但在初始化了所有必要的状态(以便工作进程可以看到此状态)之后。不再有错误或例外。
底线:多线程和多线程不能一起工作。
发布于 2013-01-08 19:41:59
“self”指的是什么类型的对象?在什么时候初始化并启动分叉进程?也许更多的代码可以帮助诊断这个问题。
好吧,这个很好:
import multiprocessing
import os
import time
import cherrypy
def run_in_sub_proc(size):
for i in range(size):
print os.getpid(), i
time.sleep(1)
pool = multiprocessing.Pool(2)
class Root(object):
@cherrypy.expose
def index(self):
pool.map_async(run_in_sub_proc, (3, 5))
if __name__ == '__main__':
cherrypy.engine.subscribe('stop', pool.join)
cherrypy.quickstart(Root())https://stackoverflow.com/questions/14222415
复制相似问题