BaseHTTPRequestHandler с пользовательским экземпляром

это мой http-сервер:

from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer

class test:
    def show(self):
        return "aaaa"

class http_server:
    def __init__(self, t1):
        self.t1 = t1
        server = HTTPServer(('', 8080), myHandler)
        server.serve_forever()

class myHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type','text/html')
        self.end_headers()
        self.wfile.write(self.t1.show()) #Doesnt work
        return

class main:
    def __init__(self):
        self.t1 = test()
        self.server = http_server(self.t1)

if __name__ == '__main__':
    m = main()

Мне нужно получить доступ к экземпляру t1 внутри myHander.

Есть ли способ, как это сделать?

Спасибо!


person Peter    schedule 26.08.2013    source источник


Ответы (5)


есть способ сделать это, чтобы установить свойство в класс:

from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer

class test:
    def show(self):
        return "aaaa"

class http_server:
    def __init__(self, t1):
        myHandler.t1 = t1
        server = HTTPServer(('', 8080), myHandler)
        server.serve_forever()

class myHandler(BaseHTTPRequestHandler):
    t1 = None
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type','text/html')
        self.end_headers()
        self.wfile.write(self.t1.show()) #Doesnt work
        return

class main:
    def __init__(self):
        self.t1 = test()

        self.server = http_server(self.t1)

if __name__ == '__main__':
    m = main()

Вы должны быть осторожны, везде, где вы используете myHandler, это будет один и тот же экземпляр t1

person Philippe T.    schedule 26.08.2013
comment
Теперь ЭТО спасло мне жизнь! Гораздо проще (по крайней мере, на данный момент) создать экземпляр класса без переопределения метода init, а затем установить handler.t1 = value. - person George; 12.07.2016
comment
Я бы никогда не подумал использовать статический член класса. Вместо этого я потратил более часа на поиски того, как получить доступ к экземпляру, который HTTPServer создает внутри (на основе класса, который вы передали ему в качестве обработчика). Излишне говорить, что это превратилось в типичную проблему курицы и яйца — конструктору обработчика требуется экземпляр сервера, которого, очевидно, нет в момент создания обработчика вне класса сервера. XD - person rbaleksandar; 15.02.2018
comment
@Филипп Т. Только что спас еще одну жизнь! Кстати, удалите этот комментарий #Doesnt work из кода. - person Dami; 25.05.2020

Немного улучшенная версия, где t1 не будет одинаковым для каждого экземпляра.

from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer

class test:
    def show(self):
        return "aaaa"

class http_server:
    def __init__(self, t1):
        def handler(*args):
            myHandler(t1, *args)
        server = HTTPServer(('', 8080), handler)
        server.serve_forever()

class myHandler(BaseHTTPRequestHandler):
    def __init__(self, t1, *args):
        self.t1 = t1
        BaseHTTPRequestHandler.__init__(self, *args)

    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type','text/html')
        self.end_headers()
        self.wfile.write(self.t1.show()) #Doesnt work
        return

class main:
    def __init__(self):
        self.t1 = test()

        self.server = http_server(self.t1)

if __name__ == '__main__':
    m = main()
person rsmoorthy    schedule 03.11.2014
comment
Привет, я не понимаю, как работает обработчик, можешь мне объяснить? Эта функция просто создает экземпляр myHandler, но ничего не возвращает. Спасибо - person Francesco; 07.02.2016
comment
@Francesco Для лучшей читабельности имело бы смысл использовать оператор return. Однако, как оказалось, класс HTTPServer просто вызывает функцию-обработчик и не беспокоится о возвращаемом ею значении. Так что не возвращать ничего по-прежнему работает. Если вы посмотрите на класс BaseServer (базовый класс для HTTPServer) — метод finish_request просто вызывает переданный RequestHandlerClass (при передаче ref самому себе), и не беспокоится об ответах от этого класса. Так что приведенный выше код работает :-) - person rsmoorthy; 08.02.2016
comment
Чтобы быть более точным, потому что это поймало меня на минуту, HTTPServer создает экземпляр обработчика, а не вызывает его (эффективно, вызывая Handler(args_to_init)). Поскольку функция handler @rsmoorthy крякает, как обычное создание экземпляра Handler, HTTPServer может создать экземпляр с ним, хотя на самом деле он просто вызывает функцию handler. Я добавил еще один ответ ниже, делая то же самое, но используя functools.partial, чтобы добавить ясности. - person Andrew; 20.05.2021

Я знаю, что отвечаю довольно поздно, но это, вероятно, может быть полезно для будущих зрителей. Существует очень простой способ получить доступ к t1, как было задано, используя переменную server объекта BaseHTTPRequestHandler:

from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer

class test:
    def show(self):
        return "aaaa"

class http_server:
    def __init__(self, t1):
        server = HTTPServer(('', 8080), myHandler)
        server.t1 = t1
        server.serve_forever()

class myHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type','text/html')
        self.end_headers()
        self.wfile.write(self.server.t1.show())
        return

class main:
    def __init__(self):
        self.t1 = test()
        self.server = http_server(self.t1)

if __name__ == '__main__':
    m = main()
person XaF    schedule 17.05.2015
comment
Хороший ответ, но я считаю, что это должно быть server.t1 = t1 вместо self.t1 = t1 в конструкторе http_server. - person ketorin; 05.11.2015
comment
а также server.t1 = t1 должен идти после назначения HTTPServer() - person Aaron_H; 16.02.2016

Еще один вариант ответа на этот вопрос 8-летней давности :) Я тоже хотел на всякий случай избежать использования переменных класса, которые являются общими для всех объектов Handler, но мне потребовалась минута, чтобы понять, почему ответ @rsmoorthy сработал. По сути, это тот же ответ, что и у него, но с использованием functools.partial для большей ясности.

Поскольку HTTPServer ожидает обработчик как RequestHandlerClass, мы не можем полностью создать экземпляр класса. Но мы можем дать нашему подклассу пользовательский __init__, который принимает дополнительные данные, а затем использовать functools.partial для заполнения этой дополнительной информации для HTTPServer. Таким образом, он просто создает экземпляр нашего обработчика, но мы все равно получаем t1 внутри.

from http.server import BaseHTTPRequestHandler, HTTPServer
import functools


class test:
    def show(self):
        return b"aaaa"

class http_server:
    def __init__(self, t1):
        handler_partial = functools.partial(Handler, t1=t1)
        server = HTTPServer(('', 8080), handler_partial)
        server.serve_forever()

class Handler(BaseHTTPRequestHandler):
    def __init__(self, *args, t1=None, **kwargs):
        # Assign before super().__init__ because init is what triggers parsing the request
        self.t1 = t1
        super().__init__(*args, **kwargs)

    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type','text/html')
        self.end_headers()
        self.wfile.write(self.t1.show())
        return

class main:
    def __init__(self):
        self.t1 = test()
        self.server = http_server(self.t1)

if __name__ == '__main__':
    m = main()
person Andrew    schedule 19.05.2021

И еще один ответ на этот старый вопрос, на этот раз с использованием фабричной функции, которая создает подклассы BaseHTTPRequestHandler с нашим уже доступным t1.

from http.server import BaseHTTPRequestHandler, HTTPServer

class test:
    def show(self):
        return b"aaaa"

class http_server:
    def __init__(self, t1):
        myHandler = handlerFactory(t1)
        server = HTTPServer(('', 8080), myHandler)
        server.serve_forever()

def handlerFactory(t1):
    class myHandler(BaseHTTPRequestHandler):
        def do_GET(self):
            self.send_response(200)
            self.send_header('Content-type','text/html')
            self.end_headers()
            self.wfile.write(t1.show())
            return
    return myHandler

class main:
    def __init__(self):
        self.t1 = test()
        self.server = http_server(self.t1)

if __name__ == '__main__':
    m = main()
person Andrew    schedule 19.05.2021