Python atexit用于清理在不同进程中运行的服务器 - 端口仍在使用中

时间:2011-04-19 17:50:31

标签: python multiprocessing

我有一些集成测试代码,可以在不同的进程中生成HTTP服务器以进行调用。此服务器可能会受到活动的污染,因此我希望能够根据需要启动和停止它的新实例。

这很遗憾没有用...我遇到了运行我的服务器的端口在我的进程退出后仍然被锁定的情况(这意味着如果我快速运行测试两次,它第二次失败,因为端口被锁定了。)

我尝试使用atexit.register绑定关机方法,但它也无法正常工作。

以下是服务器的代码:

from BaseHTTPServer import BaseHTTPRequestHandler
import SocketServer
import atexit

class RestHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/sanitycheck':
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            self.wfile.write("{ 'text': 'You are sane.' }")
        else:
            self.wfile.write(self.path)

def kill_server(httpd):
    open("/tmp/log", "w").write("KILLING")
    httpd.shutdown()

def start_simple_server(port):
    httpd = SocketServer.TCPServer(("", port), RestHTTPRequestHandler)
    atexit.register(kill_server, httpd)

    httpd.serve_forever()

    return httpd

没有任何东西写入/ tmp / log,这让我觉得atexit没有被调用。

以下是我实例化服务器的方法:

p = Process(target=start_simple_server, args=(port,))
p.start()

然后当我完成终止它时,我只是打电话:

p.terminate()

哪个会杀死进程并且应该(据我的理解)触发atexit调用 - 但它不是:(

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

终止进程时,Python atexit不会运行。

>>>import atexit
>>> def hook():
...   print "hook ran"
... 
>>> atexit.register(hook)
<function hook at 0x100414aa0>
>>> 
# in another terminal: kill <python process id>
>>> Terminated

答案 1 :(得分:0)

我采用了一种稍微不同的方法,灵感来自David Beazley的一些代码...服务器代码:

from BaseHTTPServer import BaseHTTPRequestHandler
import SocketServer
import multiprocessing
import cgi
import urlparse

class StoppableHTTPServerProcess(multiprocessing.Process):
    def __init__(self, address, handler):
        multiprocessing.Process.__init__(self)
        self.exit = multiprocessing.Event()

        self.server = StoppableHTTPServer(address, handler)

    def run(self):
        while not self.exit.is_set():
            self.server.handle_request()

    def shutdown(self):
        self.exit.set()

class RestHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.wfile.write(self.path)


class StoppableHTTPServer(SocketServer.TCPServer):
    allow_reuse_address = True
    timeout = 0.5

def start_simple_server(port):
    process = StoppableHTTPServerProcess(("", port), RestHTTPRequestHandler)
    return process

致电代码:

p = start_simple_server(port)
p.start()

当我完成了......

p.shutdown()