为什么后台任务会阻止SimpleHTTPServer中的响应? [英] Why does a background task block the response in SimpleHTTPServer?
问题描述
我正在编写一个基于浏览器的简单前端,该前端应该能够启动后台任务,然后从中获取进度.我希望浏览器收到响应,说明任务是否成功启动,然后进行轮询以确定何时完成任务.但是,后台任务的存在似乎正在阻止XMLHttpRequest响应立即发送,因此我无法报告启动该过程是否成功.考虑以下(简化)代码:
I'm writing a simple browser-based front end that should be able to launch a background task and then get progress from it. I want the browser to receive a response saying whether the task launched successfully, and then poll to determine when it is done. However, the presence of a background task seems to be stopping the XMLHttpRequest response from being sent immediately, so I can't report the success of launching the process. Consider the following (simplified) code:
import SocketServer
import SimpleHTTPServer
import multiprocessing
import time
class MyProc(multiprocessing.Process):
def run(self):
print 'Starting long process..'
for i in range(100): time.sleep(1)
print 'Done long process'
class Page(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/':
print >>self.wfile, "<html><body><a href='/run'>Run</a></body></html>"
if self.path == '/run':
self.proc = MyProc()
print 'Starting..'
self.proc.start()
print 'After start.'
print >>self.wfile, "Process started."
httpd = SocketServer.TCPServer(('', 8000), Page)
httpd.serve_forever()
运行此命令并浏览到 http://localhost:8000 时,我得到一个名为运行"的按钮. .当我单击它时,终端显示:
When I run this, and browse to http://localhost:8000, I get a button named "Run". When I click on it, the terminal displays:
Starting..
After start.
但是,浏览器视图不会更改.实际上,光标在旋转.仅当我在终端中按Ctrl-C中断程序时,浏览器才会更新,并显示消息Process started.
However the browser view does not change.. in fact the cursor is spinning. Only when I press Ctrl-C in the terminal to interrupt the program, then the browser is update with the message Process started.
消息After start
明显被打印.因此,我可以假设do_GET
在启动该过程后返回.但是,直到我中断了长时间运行的过程后,浏览器才得到响应.我必须得出结论,在do_GET
与正在发送的响应之间存在某些阻塞,该阻塞位于SimpleHTTPServer
内部.
The message After start
is clearly being printed. Therefore I can assume that do_GET
is returning after starting the process. Yet, the browser doesn't get a response until after I interrupt the long-running process. I have to conclude there is something blocking between do_GET
and the response being sent, which is inside SimpleHTTPServer
.
我也尝试过使用线程和subprocess.Popen来解决这个问题,但是遇到了类似的问题.有什么想法吗?
I've also tried this with threads and subprocess.Popen but ran into similar problems. Any ideas?
推荐答案
除了史蒂夫(Steve)和我在上面的评论之外,这是一个对我有用的解决方案.
In addition to Steve's and my comments above, here is a solution that works for me.
确定内容长度的方法有点难看.如果未指定,则尽管显示了内容,但浏览器仍可能显示旋转的光标.相反,也可以关闭self.wfile
.
The method to determine a content-length is a bit ugly. If you don't specify one, the browser may still show a spinning cursor although the content is shown. Closing the self.wfile
instead could also work.
from cStringIO import StringIO
class Page(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
out = StringIO()
self.send_response(200)
self.send_header("Content-type", "text/html")
if self.path == '/':
out.write("<html><body><a href='/run'>Run</a></body></html>\n")
elif self.path == '/run':
self.proc = MyProc()
print 'Starting..'
self.proc.start()
print 'After start.'
out.write("<html><body><h1>Process started</h1></body></html>\n")
text = out.getvalue()
self.send_header("Content-Length", str(len(text)))
self.end_headers()
self.wfile.write(text)
这篇关于为什么后台任务会阻止SimpleHTTPServer中的响应?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!