在Python中重新启动HTTP服务器的正确方法

在Python中重新启动HTTP服务器的正确方法,python,http,webserver,Python,Http,Webserver,我正在使用下面的代码片段用Python编写HTTP服务器。服务器工作正常,直到发生导致其重新启动的IOR错误。我的重启处理有问题,因为服务器启动正常,但之后不接受任何请求 这个代码有什么错误吗 #!/bin/python from BaseHTTPServer import HTTPServer import json import config import time import socket from SimpleHTTPServer import SimpleHTTPRequestHan

我正在使用下面的代码片段用Python编写HTTP服务器。服务器工作正常,直到发生导致其重新启动的IOR错误。我的重启处理有问题,因为服务器启动正常,但之后不接受任何请求

这个代码有什么错误吗

#!/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')
运行此操作的一个url是
http://localhost:9001/?cmd=some_command
。只要在服务器启动后将其粘贴到任何浏览器中即可

编辑:

我想这与KVM或它在我公司机器上的设置方式有关。由于我的服务器运行在只能通过ssh访问的KVM上,每次我退出ssh会话时,调用上面的url命令(在chrome中),等待chrome通知not connected,返回ssh会话,再次调用url命令,就会发生错误

我将调试消息放在
self.send\u response(200)
中do\u GET()的写入响应之间。当异常发生时,这是我得到的跟踪。我想这与
sys.stderr.write
内部日志消息有关

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\u message()
而不执行任何操作时,问题就消失了。我知道这只是隐藏了问题,但至少对我来说是暂时的。

sys.stderr将消息写入标准输出,通常是启动程序的shell控制台。因此,如果shell控制台关闭,sys.stderr.writes将引发IO错误

因此,问题的根本原因是log_message()函数中的sys.stderr.write试图将消息写入最初启动python程序的ssh shell控制台(标准输出),因此如果保持ssh会话活动,问题就不会发生。但是如果退出原始ssh会话,shell控制台将关闭,那么sys.stderr.write无法将消息写入原始控制台,然后发生IO错误。。。。log_消息通常会这样写:

127.0.0.1 - - [01/Dec/2015 20:16:32] "GET / HTTP/1.1" 200 -
因此,解决方案是运行python脚本,将标准输出重定向到/dev/null,如下所示:

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

Holp它有帮助。

您考虑过使用吗?那么你就不必担心这些事情了……或者。当我尝试时,你的代码就可以工作了:服务器在5秒钟后重新启动并再次接受连接。但是我不得不入侵SocketServer.py以假装失败,因为我无法从SERVER_forever()中获得异常。你需要先发布一个例子,让我们重现问题。@ArminRigo我编辑了我的文章,希望我能给你更多信息。JonClements和syrion:目前,我必须坚持使用标准Python作为我项目的需求,因为您的代码仍然无法运行。我不得不编辑它。我同意你在那里犯错误是很奇怪的。但是我尝试在那个地方添加“raiseioerror”,异常被很好地捕获:它仍然没有进入“Error ocurs.Retry in 5 seconds”路径。你能提供一个完全独立的例子吗?一种开箱即用的方法(仅在外部导入足够标准的情况下才取决于它们),允许我们通过简单地运行它来重现错误。不要遗漏任何东西;一个有效的示例比一个截断的示例要好得多。