从另一个线程关闭Python BasicHTTPServer

时间:2015-01-09 12:05:07

标签: python

我有一个脚本在线程中设置BasicHTTPServer,以便主脚本可以自动打开指向服务器url的Web浏览器以下载文件。下载文件后,我想关闭该服务器,但我不知道如何去做。这是我目前所做的一个例子:

def server():
    HandlerClass = SimpleHTTPRequestHandler
    ServerClass = BaseHTTPServer.HTTPServer
    Protocol = 'HTTP/1.0'

    server_address = ('127.0.0.1', 8000)
    HandlerClass.protocol_version = Protocol
    httpd = ServerClass(server_address, HandlerClass)
    httpd.serve_forever()

def download():
    t = threading.Thread(name='server', target=server)
    t.start()
    webbrowser.open('safari-http://127.0.0.1:8000/')

我想在webbrowser.open()之后关闭服务器。

谢谢

3 个答案:

答案 0 :(得分:1)

我尝试了here给出的示例。你能检查一下它是否适合你。

runFlag = True
def server(server_class=BaseHTTPServer.HTTPServer,
                   handler_class=BaseHTTPServer.BaseHTTPRequestHandler):
    global runFlag
    server_address = ('127.0.0.1', 8000)
    HandlerClass.protocol_version = Protocol
    httpd = ServerClass(server_address, HandlerClass)
    while runFlag:
        httpd.handle_request()
    httpd.shutdown()

def download():
    t = threading.Thread(name='server', target=server)
    t.start()
    webbrowser.open('https:\\www.google.com')
    global runFlag 
    runFlag = False

答案 1 :(得分:0)

以下是cryptoassets.core project, status server的示例:

class StatusHTTPServer(threading.Thread):

    def __init__(self, ip, port):
        threading.Thread.__init__(self)
        self.running = False
        self.ready = False
        self.ip = ip
        self.port = port

    def run(self):
        self.running = True
        self.ready = True
        self.httpd.serve_forever()
        self.running = False

    def start(self):
        server_address = (self.ip, self.port)
        try:
            self.httpd = HTTPServer(server_address, StatusGetHandler)
        except OSError as e:
            raise RuntimeError("Could not start cryptoassets helper service status server at {}:{}".format(self.ip, self.port)) from e

        threading.Thread.start(self)

    def stop(self):
        if self.httpd and self.running:
            self.httpd.shutdown()
            self.httpd = None

答案 2 :(得分:0)

因此,在深入研究了许多文章之后,我设法找到了一种对我来说完全关闭服务器的凌乱解决方案。为此,我整合了以下来源的代码:

UI是iOS Python IDE Python独有的模块,它基本上只创建按钮" start"," stop"和"访问"它们绑定到各自的_t函数。 ui.in_background装饰器只是让ui在后台发生事件时保持响应。 self.httpd.socket.close()真正关闭了服务器,但是它很乱并且向stdout / err输出一个丑陋的错误所以我别无选择,只能通过将stdout / err重定向到死类来抑制它,这样就会丢失错误。标准stdout / err行为在之后立即恢复。感谢大家花时间和精力帮助我,我非常感激。

import console
import BaseHTTPServer
import SocketServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
import sys
import threading
import webbrowser
from time import sleep
import ui

original_stdout = sys.stdout
original_stderr = sys.stderr


class BasicServer(SocketServer.TCPServer):
    allow_reuse_address = True

class NullifyOutput():
    def write(self, s):
        pass

class ServerThread(threading.Thread):
    def __init__(self, ip, port):
        super(ServerThread, self).__init__()
        self.ip = ip
        self.port = port
        self.HandlerClass = SimpleHTTPRequestHandler
        self.Protocol = 'HTTP/1.0'
        self.server_address = (self.ip, self.port)
        self.HandlerClass.protocol_version = self.Protocol
        try:
            self.httpd = BasicServer(self.server_address, self.HandlerClass)
        except:
            self.port += 1
            self.server_address = (self.ip, self.port)
            self.httpd = BasicServer(self.server_address, self.HandlerClass)
        self.stoptheserver = threading.Event()


    def run(self):
        while not self.stoptheserver.isSet():
            self.httpd.handle_request()


    def join(self, timeout=None):
        self.stoptheserver.set()
        self.httpd.socket.close()
        super(ServerThread, self).join(timeout)


server = ServerThread('127.0.0.1', 8000)

def start_t(sender):
    print server.isAlive()
    if not server.isAlive():
        server.start()


def visit_t(sender):
    webbrowser.open('http://127.0.0.1:' + str(server.port))
    #webbrowser.open('safari-http://127.0.0.1' + str(server.port))
    # Use the safari- prefix to open in safari. You may need to switch to
    # pythonista then back to safari to get the page to load.

@ui.in_background
def stop_t(sender):
    sys.stdout, sys.stderr = NullifyOutput(), NullifyOutput()
    server.join(3)
    sys.stdout, sys.stderr = original_stdout, original_stderr

ui.load_view('SimpleServer').present('sheet')