RequestHandler にパラメータを渡すにはどうすればいいですか? 質問する

RequestHandler にパラメータを渡すにはどうすればいいですか? 質問する

Pythonのドキュメントには以下が含まれていますHTTPサーバーの作成例:

def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):
    server_address = ('', 8000)
    httpd = server_class(server_address, handler_class)
    httpd.serve_forever()

RequestHandlerにクラスが提供され、Serverハンドラーのインスタンス化が自動的に処理されます。

リクエスト ハンドラーの作成時にカスタム パラメーターを渡したいとします。どうすればよいでしょうか。また、どうすればよいでしょうか。

もっと具体的に言うと、コマンド ラインからパラメータを渡したいのですが、sys.argvリクエスト ハンドラ クラス内でアクセスする必要があるのは不必要に面倒に思えます。

これはクラスの一部をオーバーライドすることで可能になるように思えますServerが、よりシンプルで優れた解決策を見落としているような気がします。

ベストアンサー1

私は自分のコードで「部分適用」を使ってこれを解決しました。Pythonの標準ライブラリはこれを次のように提供しています。functools.partial

例は Python 3 を使用して記述されていますが、部分適用は Python 2 でも同じように動作します。

from functools import partial
from http.server import HTTPServer, BaseHTTPRequestHandler

class ExampleHandler(BaseHTTPRequestHandler):
    def __init__(self, foo, bar, qux, *args, **kwargs):
        self.foo = foo
        self.bar = bar
        self.qux = qux
        # BaseHTTPRequestHandler calls do_GET **inside** __init__ !!!
        # So we have to call super().__init__ after setting attributes.
        super().__init__(*args, **kwargs)

    def do_HEAD(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/plain')
        self.end_headers()

    def do_GET(self):
        self.do_HEAD()
        self.wfile.write('{!r} {!r} {!r}\n'
                         .format(self.foo, self.bar, self.qux)
                         .encode('utf8'))

# We "partially apply" the first three arguments to the ExampleHandler
handler = partial(ExampleHandler, sys.argv[1], sys.argv[2], sys.argv[3])
# .. then pass it to HTTPHandler as normal:
server = HTTPServer(('', 8000), handler)
server.serve_forever()

これはクラス ファクトリーと非常に似ていますが、私の意見では、いくつかの微妙な利点があります。

  • partialオブジェクトは、ファクトリ関数によって定義され返されるネストされたクラスよりも、その内部にあるものをイントロスペクトする方がはるかに簡単です。
  • partial現代の Python ではオブジェクトはシリアル化できますが、ファクトリ関数内のネストされたクラス定義はシリアル化できません (少なくとも、それを可能にするためにクラスにメソッドpickleをコーディングしない限りは)。__reduce__
  • partial私の限られた経験では、Pythonの通常のクラス定義に明示的に引数を「事前に追加する」ことは、より簡単に(認知負荷が少ない)読む、理解する、正確性を確認するラッピング関数のパラメータが内部のどこかに埋め込まれたネストされたクラス定義よりも優れています。

唯一の欠点は、多くの人が馴染みがないことですpartialが、私の経験では、みんななるとにかく、ここのように、時には予期せず、多くの場所で簡単で構成可能なソリューションとして現れる方法があるpartialため、よく知られています。partial

おすすめ記事