为什么后台任务会阻止SimpleHTTPServer中的响应? [英] Why does a background task block the response in SimpleHTTPServer?

查看:81
本文介绍了为什么后台任务会阻止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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆