4

以下のコード スニペットを使用して、Python で HTTP サーバーを作成しています。サーバーは、何らかの IOError が発生して再起動するまで正常に動作します。サーバーは正常に起動しますが、その後はリクエストを受け付けないため、再起動処理に問題があります。

このコードに何か問題がありますか?

#!/bin/python
from BaseHTTPServer import HTTPServer
import json
import config
import time
import socket
from SimpleHTTPServer import SimpleHTTPRequestHandler
from SocketServer import BaseServer


class MyHandler(SimpleHTTPRequestHandler):
   def parseArgs(self):
        args = {}
        try:
            config.logging.info(self.path)
            args_list = self.path.split("?")[1].split("&")
            for entry in args_list:
               args[entry.split("=")[0]] = entry.split("=")[1]
        except IndexError:
            pass
        return args

   def do_GET(self):
      try:
        response = {}
        args = self.parseArgs()
        config.logging.debug("Handle the request")
        self._handle_request(args, response)
        config.logging.debug("Write the header back to the client.")
        self.send_response(200)
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Content-Type:', 'application/json; charset=UTF-8')
        self.end_headers()
        config.logging.debug("Finish writing the header and start writing JSON response.")
        json_encoded = json.dumps(response)
        config.logging.debug(json_encoded)
        self.wfile.write(json_encoded)
        config.logging.debug("JSON Response written successfully.")
      except Exception as e:
        config.logging.exception('Exception occurs when writing back the response.')
      return

   def _handle_request(self, args, response):
      try:
        response["sysTime"] = long(round(time.time() * 1000))
        if not "cmd" in args:
           response["message"] = "Error: No command provided."
        else:
           response["message"] = args['cmd']
      except Exception as e:
          response["message"] = "Error: Exception occurs (check logs)."
          config.logging.exception('Exception occurs when handling request.')

   def do_POST(self):
       self.send_response(200)
       self.send_header('Content-type',     'text/html')
       self.end_headers()
       self.wfile.write("Nothing here :( ")

def main():
   while True:
    try:
        httpd = HTTPServer(('', config.listening_port), MyHandler)
        sa = httpd.socket.getsockname()
        msg = "Serving HTTP on " + sa[0] + " port " + str(sa[1]) + "..."
        print msg
        config.logging.info(msg)
        httpd.serve_forever()
    except KeyboardInterrupt:
        print '^C received, shutting down server'
        config.logging.info('^C received, shutting down server')
        httpd.socket.close()
        break
    except Exception as e:
        httpd.shutdown()
        httpd.socket.close()
        print "Error occurs. Retry in 5 seconds"
        config.logging.exception('Exception occurs. Retry in 5 seconds.')
        time.sleep(5)

if __name__ == '__main__':
    main()

モジュールの設定が抜けていてすみません。

import logging

# global variables
listening_port = 9001
logging.basicConfig(filename='error.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')

これを実行するための 1 つの URL はhttp://localhost:9001/?cmd=some_command. サーバーの起動後、それを任意のブラウザーに貼り付けるだけです。

編集:

これは、KVM または会社のマシンでのセットアップ方法に関係があると思います。サーバーは ssh 経由でのみアクセスできる KVM で実行されているため、ssh セッションを終了するたびに、上記の url コマンドを (chrome で) 呼び出し、chrome が接続されていないことを通知するまで待ち、ssh セッションに戻り、url を呼び出しますコマンドを再度実行すると、エラーが発生しました。

の do_GET() の書き込み応答の間にデバッグ メッセージを挿入しましたself.send_response(200)。例外が発生したとき、これが得られたトレースです。sys.stderr.writelog_message 内で何か関係があると思います。

11/23/2012 10:58:29 AM - INFO - Handle the request
11/23/2012 10:58:29 AM - INFO - /?cmd=get_info&uid=pp
11/23/2012 10:58:29 AM - INFO - Write the header back to the client.
11/23/2012 10:58:29 AM - ERROR - Exception occurs when writing back the response.
Traceback (most recent call last):
   File "service.py", line 57, in do_GET
      self.send_response(200)
   File "/usr/lib/python2.7/BaseHTTPServer.py", line 385, in send_response
      self.log_request(code)
   File "/usr/lib/python2.7/BaseHTTPServer.py", line 422, in log_request
      self.requestline, str(code), str(size))
   File "/usr/lib/python2.7/BaseHTTPServer.py", line 458, in log_message
      format%args))
   IOError: [Errno 5] Input/output error

編集:

log_message()何もしないようにオーバーライドすると、問題はなくなりました。これは問題を隠すだけであることは知っていますが、少なくとも一時的には機能します。

4

1 に答える 1

-1

sys.stderr は、メッセージを標準出力 (通常はプログラムを開始したシェル コンソール) に書き込みます。そのため、シェル コンソールが閉じられると、sys.stderr.writes で IO エラーが発生します。

したがって、問題の根本的な原因は、log_message() 関数の sys.stderr.write が、最初に Python プログラムを開始した ssh シェル コンソール (標準出力) にメッセージを書き込もうとすることです。 、問題は発生しません。しかし、元の ssh セッションを終了すると、シェル コンソールが閉じられ、sys.stderr.write が元のコンソールにメッセージを書き込めなくなり、IO エラーが発生します.... log_message は通常、次のような内容を書き込みます。

127.0.0.1 - - [01/Dec/2015 20:16:32] "GET / HTTP/1.1" 200 -

したがって、解決策は、次のように標準出力を /dev/null にリダイレクトして Python スクリプトを実行することです。

python your_script.py > /dev/null 2>&1 &

それが役立ちます。

于 2015-12-01T12:29:06.127 に答える