21

socketserver にはshutdown()サーバーをシャットダウンするメソッドがあることは知っていますが、シャットダウンは実行中のスレッドとは異なるスレッドから呼び出す必要があるため、これは複数のスレッドアプリケーションでのみ機能しますserve_forever()

私のアプリケーションは一度に 1 つのリクエストしか処理しないので、リクエストの処理に個別のスレッドを使用せず、shutdown()デッドロックが発生するため呼び出すことができません (ドキュメントにはありませんが、socketserver のソース コードに直接記載されています)。

理解を深めるために、コードの簡略版をここに貼り付けます。

import socketserver

class TCPServerV4(socketserver.TCPServer):
  address_family = socket.AF_INET
  allow_reuse_address = True

class TCPHandler(socketserver.BaseRequestHandler):
  def handle(self):
    try:
       data = self.request.recv(4096)
    except KeyboardInterrupt:
       server.shutdown()

server = TCPServerV4((host, port), TCPHandler)
server.server_forever()

このコードが機能していないことは承知しています。ユーザーがCtrlC.

4

7 に答える 7

20
于 2014-03-20T13:05:52.353 に答える
14

SocketServer ライブラリは、継承された属性を処理するためにいくつかの奇妙な方法を使用します (古いスタイルのクラスの使用による推測)。サーバーを作成してその保護された属性を一覧表示すると、次のように表示されます。

In [4]: server = SocketServer.TCPServer(('127.0.0.1',8000),Handler)
In [5]: server._

server._BaseServer__is_shut_down
server.__init__
server._BaseServer__shutdown_request
server.__module__
server.__doc__
server._handle_request_nonblock

リクエストハンドラーに次を追加するだけの場合:

self.server._BaseServer__shutdown_request = True

サーバーがシャットダウンします。server.shutdown()これは、シャットダウンするまで待つ (メインスレッドをデッドロックする) ことなく、 を呼び出すのと同じことを行います。

于 2016-03-15T17:07:42.753 に答える
3

shutdownソースコードで指摘されているように、実際には他のスレッドで呼び出す必要があります。

 def shutdown(self):
        """Stops the serve_forever loop.

        Blocks until the loop has finished. This must be called while
        serve_forever() is running in another thread, or it will
        deadlock.
        """
        self.__shutdown_request = True
        self.__is_shut_down.wait()
于 2013-08-18T08:01:46.647 に答える
2

TCP ハンドラーで をキャッチしない場合KeyboardInterrupt(または再度発生させる場合)、ルート呼び出し (この場合はserver_forever()呼び出し) まで細流化する必要があります。

ただし、これはテストしていません。コードは次のようになります。

import socketserver  # Python2: SocketServer

class TCPServerV4(socketserver.TCPServer):
    address_family = socket.AF_INET
    allow_reuse_address = True

class TCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data = self.request.recv(4096)

server = TCPServerV4((host, port), TCPHandler)

try:
    server.serve_forever()
except KeyboardInterrupt:
    server.shutdown()
于 2012-04-10T09:27:49.163 に答える
1

いつでもシグナルを試すことができます:

import signal
import os

# inside handler code that has decided to shutdown:
os.kill(os.getpid(), signal.SIGHUP)    # send myself sighup
于 2014-09-10T17:14:19.180 に答える