我正在尝试创建一个为用户提供简单HTML表单的应用程序,然后在用户提交表单时调用函数。它使用wsgiref.simple_server来提供HTML。服务器遇到错误,我无法理解原因。代码如下:
#!/usr/bin/python3
from wsgiref.simple_server import make_server
from wsgiref.util import setup_testing_defaults
import webbrowser # open user's web browser to url when server is run
from sys import exc_info
from traceback import format_tb
# Easily serves an html form at path_to_index with style at path_to_style
# Calls on_submit when the form is submitted, passing a dictionary with key
# value pairs { "input name" : submitted_value }
class SimpleServer:
def __init__(self, port=8000, on_submit=None, index_path="./index.html", css_path="./style.css"):
self.port = port
self.on_submit = on_submit
self.index_path = index_path
self.css_path = css_path
# Forwards request to proper method, or returns 404 page
def wsgi_app(self, environ, start_response):
urls = [
(r"^$", self.index),
(r"404$", self.error_404),
(r"style.css$", self.css)
]
path = environ.get("PATH_INFO", "").lstrip("/")
# Call another application if they called a path defined in urls
for regex, application in urls:
match = re.search(regex, path)
# if the match was found, return that page
if match:
environ["myapp.url_args"] = match.groups()
return application(environ, start_response)
return error_404(environ, start_response)
# Gives the user a form to submit all their input. If the form has been
# submitted, it sends the ouput of self.on_submit(user_input)
def index(self, environ, start_response):
# user_input is a dictionary, with keys from the names of the fields
user_input = parse_qs(environ['QUERY_STRING'])
# return either the form or the calculations
index_html = open(self.index_path).read()
body = index_html if user_input == {} else calculate(user_input)
mime_type = "text/html" if user_input == {} else "text/plain"
# return the body of the message
status = "200 OK"
headers = [ ("Content-Type", mime_type),
("Content-Length", str(len(body))) ]
start_response(status, headers)
return [body.encode("utf-8")]
def start_form(self):
httpd = make_server('', self.port, ExceptionMiddleware(self.wsgi_app))
url = "http://localhost:" + str(self.port)
print("Visit " + url)
# webbrowser.open(url)
httpd.serve_forever()
if __name__ == "__main__":
server = SimpleServer()
server.start_form()
当我运行它时,我收到错误
127.0.0.1 - - [16/Dec/2014 21:15:57] "GET / HTTP/1.1" 500 0
Traceback (most recent call last):
File "/usr/lib/python3.4/wsgiref/handlers.py", line 138, in run
self.finish_response()
File "/usr/lib/python3.4/wsgiref/handlers.py", line 180, in finish_response
self.write(data)
File "/usr/lib/python3.4/wsgiref/handlers.py", line 266, in write
"write() argument must be a bytes instance"
AssertionError: write() argument must be a bytes instance
127.0.0.1 - - [16/Dec/2014 21:15:57] "GET / HTTP/1.1" 500 59
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 49354)
Traceback (most recent call last):
File "/usr/lib/python3.4/wsgiref/handlers.py", line 138, in run
self.finish_response()
File "/usr/lib/python3.4/wsgiref/handlers.py", line 180, in finish_response
self.write(data)
File "/usr/lib/python3.4/wsgiref/handlers.py", line 266, in write
"write() argument must be a bytes instance"
AssertionError: write() argument must be a bytes instance
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.4/wsgiref/handlers.py", line 141, in run
self.handle_error()
File "/usr/lib/python3.4/wsgiref/handlers.py", line 368, in handle_error
self.finish_response()
File "/usr/lib/python3.4/wsgiref/handlers.py", line 180, in finish_response
self.write(data)
File "/usr/lib/python3.4/wsgiref/handlers.py", line 274, in write
self.send_headers()
File "/usr/lib/python3.4/wsgiref/handlers.py", line 331, in send_headers
if not self.origin_server or self.client_is_modern():
File "/usr/lib/python3.4/wsgiref/handlers.py", line 344, in client_is_modern
return self.environ['SERVER_PROTOCOL'].upper() != 'HTTP/0.9'
TypeError: 'NoneType' object is not subscriptable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.4/socketserver.py", line 305, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/lib/python3.4/socketserver.py", line 331, in process_request
self.finish_request(request, client_address)
File "/usr/lib/python3.4/socketserver.py", line 344, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usr/lib/python3.4/socketserver.py", line 669, in __init__
self.handle()
File "/usr/lib/python3.4/wsgiref/simple_server.py", line 133, in handle
handler.run(self.server.get_app())
File "/usr/lib/python3.4/wsgiref/handlers.py", line 144, in run
self.close()
File "/usr/lib/python3.4/wsgiref/simple_server.py", line 35, in close
self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'
这个输出实际上并不包含我正在运行的脚本,我很困惑。有什么想法吗?
答案 0 :(得分:2)
只是为这个问题注册解决方案,问题在于len()函数。
STR(LEN(本体))
计算错误的大小,并在返回服务器Content-Length时,等待所需的更多字节。
因此,总是使用UTF-8缓冲区发送字节,例如:
from io import StringIO
stdout = StringIO()
print("Hello world!", file=stdout)
start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')])
return [stdout.getvalue().encode("utf-8")]
答案 1 :(得分:1)
查看您的代码,我没有看到此错误的直接原因。但是,我强烈建议,除非您尝试了解wsgi的工作原理(或实现自己的框架),否则您应该使用现有的微框架。 WSGI并不意味着应用程序直接使用。它在Python和Web服务器之间提供了一个非常精简的接口。
一个漂亮而轻巧的框架是bottle.py - 我将它用于所有Python webapps。但是还有很多其他的,寻找"非全栈框架"在https://wiki.python.org/moin/WebFrameworks。
瓶子的一个很好的优点是它只是一个文件,因此可以很容易地与您的服务器一起分发。