代码之家  ›  专栏  ›  技术社区  ›  Erik

TypeError:需要类似字节的对象,而不是“str”WSGI服务器

  •  0
  • Erik  · 技术社区  · 8 年前

    TypeError: a bytes-like object is required, not 'str'
    

    import socket
    #import StringIO
    import io
    import sys
    
    
    class WSGIServer(object):
        address_family = socket.AF_INET
        socket_type = socket.SOCK_STREAM
        request_queue_size = 1
    
        def __init__(self, server_address):
            # Create a listening socket
            self.listen_socket = listen_socket = socket.socket(
                self.address_family,
                self.socket_type
            )
            # Allow to reuse the same address
            listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            # Bind
            listen_socket.bind(server_address)
            # Activate
            listen_socket.listen(self.request_queue_size)
            # Get server host name and port
            host, port = self.listen_socket.getsockname()[:2]
            self.server_name = socket.getfqdn(host)
            self.server_port = port
            # Return headers set by Web framework/Web application
            self.headers_set = []
    
        def set_app(self, application):
            self.application = application
    
        def serve_forever(self):
            listen_socket = self.listen_socket
            while True:
                # New client connection
                self.client_connection, client_address = listen_socket.accept()
                # Handle one request and close the client connection. Then
                # loop over to wait for another client connection
                self.handle_one_request()
    
        def handle_one_request(self):
            self.request_data = request_data = self.client_connection.recv(1024)
            # Print formatted request data a la 'curl -v'
            print(''.join(
                '< {line}\n'.format(line=line)
                for line in request_data.splitlines()
            ))
    
            self.parse_request(request_data)
    
            # Construct environment dictionary using request data
            env = self.get_environ()
    
            # It's time to call our application callable and get
            # back a result that will become HTTP response body
            result = self.application(env, self.start_response)
    
            # Construct a response and send it back to the client
            self.finish_response(result)
    
        def parse_request(self, text):
            request_line = text.splitlines()[0]
            request_line = request_line.rstrip('\r\n')
            # Break down the request line into components
            (self.request_method,  # GET
             self.path,            # /hello
             self.request_version  # HTTP/1.1
             ) = request_line.split()
    
        def get_environ(self):
            env = {}
            # The following code snippet does not follow PEP8 conventions
            # but it's formatted the way it is for demonstration purposes
            # to emphasize the required variables and their values
            #
            # Required WSGI variables
            env['wsgi.version']      = (1, 0)
            env['wsgi.url_scheme']   = 'http'
            env['wsgi.input']        = io.StringIO(self.request_data)
            env['wsgi.errors']       = sys.stderr
            env['wsgi.multithread']  = False
            env['wsgi.multiprocess'] = False
            env['wsgi.run_once']     = False
            # Required CGI variables
            env['REQUEST_METHOD']    = self.request_method    # GET
            env['PATH_INFO']         = self.path              # /hello
            env['SERVER_NAME']       = self.server_name       # localhost
            env['SERVER_PORT']       = str(self.server_port)  # 8888
            return env
    
        def start_response(self, status, response_headers, exc_info=None):
            # Add necessary server headers
            server_headers = [
                ('Date', 'Tue, 31 Mar 2015 12:54:48 GMT'),
                ('Server', 'WSGIServer 0.2'),
            ]
            self.headers_set = [status, response_headers + server_headers]
            # To adhere to WSGI specification the start_response must return
            # a 'write' callable. We simplicity's sake we'll ignore that detail
            # for now.
            # return self.finish_response
    
        def finish_response(self, result):
            try:
                status, response_headers = self.headers_set
                response = 'HTTP/1.1 {status}\r\n'.format(status=status)
                for header in response_headers:
                    response += '{0}: {1}\r\n'.format(*header)
                response += '\r\n'
                for data in result:
                    response += data
                # Print formatted response data a la 'curl -v'
                print(''.join(
                    '> {line}\n'.format(line=line)
                    for line in response.splitlines()
                ))
                self.client_connection.sendall(bytes(http_response, 'utf-8'))
            finally:
                self.client_connection.close()
    
    
    SERVER_ADDRESS = (HOST, PORT) = '', 8888
    
    
    def make_server(server_address, application):
        server = WSGIServer(server_address)
        server.set_app(application)
        return server
    
    
    if __name__ == '__main__':
        if len(sys.argv) < 2:
            sys.exit('Provide a WSGI application object as module:callable')
        app_path = sys.argv[1]
        module, application = app_path.split(':')
        module = __import__(module)
        application = getattr(module, application)
        httpd = make_server(SERVER_ADDRESS, application)
        print('WSGIServer: Serving HTTP on port {port} ...\n'.format(port=PORT))
        httpd.serve_forever()
    

    错误是:

    enter image description here

    1 回复  |  直到 8 年前
        1
  •  5
  •   Martijn Pieters    6 年前

    bytes 此处的方法:

    request_line = request_line.rstrip('\r\n')
    

    request_line 字节数 str 对象你需要通过一个 字节数 要剥离的对象;使用 b'...' 字节字符串文字:

    request_line = request_line.rstrip(b'\r\n')
    

    StringIO 对象,但又有字节。Python 3上的WSGI使用 文件对象:

    env['wsgi.input']        = io.BytesIO(self.request_data)
    

    然而,如果您只想部署一个Django项目,请立即停止。你知道 需要编写自己的WSGI服务器来实现这一点。您找到的代码是一个示例WSGI服务器,在实际负载下无法正常工作,仅用于说明WSGI的工作原理。

    对于Django部署,请阅读 How to deploy with WSGI documentation how WSGI servers work .