2015-01-09 4 views
4

У меня есть сценарий, который устанавливает BasicHTTPServer в потоке, чтобы основной скрипт мог автоматически открыть веб-браузер, указывающий на сервер url, чтобы загрузить файл. После того, как файл будет загружен, я хочу отключить этот сервер, но я не знаю, как это сделать. Это пример того, что я сделал в настоящее время:Завершение работы Python BasicHTTPServer из другого потока

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().

Спасибо

+0

https://docs.python.org/2/library/socketserver.html#SocketServer.BaseServer.shutdown –

+0

Просто хотелось бы отметить, что я знаю о методе BaseServer.shutdown(), но у меня есть не знаю, как его реализовать в этой ситуации. – HeyItsJono

+0

Не работает, к сожалению. Говорит, что нет глобальной переменной httpd. Перемещение всего, за исключением выражения «httpd.serve_forever()» за пределами функции server(), просто заставляет программу зависать при вызове функции download(). – HeyItsJono

ответ

0

Таким образом, после копать глубоко через много статей мне удалось найти свой род грязного решения, которое работает для меня, который полностью закрывает сервер. Для того, чтобы сделать это я включил код из следующих источников:

UI представляет собой модуль исключительно для IOS Python IDE Pythonista, которые в основном просто создает кнопку "старт", «стоп »и« visit », которые привязаны к их соответствующим функциям _t. Декодер ui.in_background просто позволяет ui оставаться отзывчивым, в то время как все происходит в фоновом режиме. - это то, что действительно закрывает сервер, но оно беспорядочно и печатает уродливую ошибку в 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') 
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 
+0

Итак, любой экземпляр этого будет работать в отдельном потоке, и я могу вызвать stop() из любого места, чтобы остановить его? – HeyItsJono

+0

@HeyItsJono: Да, это в значительной степени. –

+0

Это все еще не работает. Вызов stop() завершается успешно, но сам сервер фактически не останавливается, поэтому http.shutdown() по какой-то причине не работает. – HeyItsJono

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 
+0

Благодарим за помощь. Это похоже на то, что после того, как runFlag изменен на False, сервер перестает обслуживать запросы, однако, когда я снова запускаю скрипт, я получаю сообщение об ошибке: _ [Errno 48] Адрес уже используется_ указывает, что что-то все еще связывается вверх по адресу. Таким образом, сервер останавливается по большей части, но не освобождает адрес или порт. Любая идея, как это исправить? – HeyItsJono

+0

Также есть ли способ обойти это без использования глобальных переменных. Все, что я читал, говорит мне держаться подальше от них. – HeyItsJono

+0

@HeyItsJono Извините за поздний ответ, поскольку я не играю с компьютерами в выходные дни. 'Ошибка: 48' имеет решение здесь http://stackoverflow.com/a/19071568/2382792 Хорошо, что вы уже разместили решение !! –

Смежные вопросы