Python3.6.4 中的 SimpleHTTPServer 无法处理非 ASCII 字符串(我的情况是中文)

SimpleHTTPServer in Python3.6.4 can not handle non-ASCII string(Chinese in my case)

I 运行 SimpleHTTPServer in Python3.6.4 64bit 通过这个命令:

python -m http.server --cgi

然后我在test.py中制作一个表格,提交给test_form_action.py打印输入文本。

cgi-bin/test.py

# coding=utf-8
from __future__ import unicode_literals, absolute_import

print("Content-Type: text/html")  # HTML is following
print()
reshtml = '''<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
</head>
<body>
<div style="text-align: center;">
    <form action="/cgi-bin/test_form_action.py" method="POST"
          target="_blank">
        输入:<input type="text" id= "id" name="name"/></td>
        <button type="submit">Submit</button>
    </form>
</div>
</body>
</html>'''

print(reshtml)

cgi-bin/test_form_action.py

# coding=utf-8
from __future__ import unicode_literals, absolute_import

# Import modules for CGI handling
import cgi, cgitb
cgitb.enable()

if __name__ == '__main__':
    print("Content-Type: text/html")  # HTML is following
    print()

    form = cgi.FieldStorage()
    print(form)
    id = form.getvalue("id")
    name = form.getvalue("name")

    print(id)

当我访问http://127.0.0.1:8000/cgi-bin/test.py时, 汉字“输入”不正确,看起来像“����”, 我必须手动更改此页面的文本编码 "Unicode" 到 "Chinese Simplified" 在 Firefox 中使汉字看起来正常。

这很奇怪,因为我把 charset="utf-8" 放在 cgi-bin/test.py.

更进一步,当我在输入表单中输入一些中文并提交时。但是 cgi-bin/test_form_action.py 是空白的。

同时在 windows 终端中显示一些错误,我 运行 SimpleHTTPServer:

127.0.0.1 - - [23/Mar/2018 23:43:32] b'Error in sys.excepthook:\r\nTraceback (most recent call last):\r\n File "E:\Python\Python36\Lib\cgitb.py", line 26 8, in call\r\n
self.handle((etype, evalue, etb))\r\n File "E:\Python\Python36\Lib\cgitb.py", line 288, in handle\r\n
self.file.write(doc + \'\ n\')\r\nUnicodeEncodeError: \'gbk\' codec can\'t encode character \'\ufffd\' in position 1894: illegal multibyte sequence\r\n\r\nOriginal exception was:\r\nT raceback (most recent call last):\r\n File "G:\Python\Project\VideoHelper\cgi-bin\test_form_action.py", line 13, in \r\n print(form)\r\nUnico deEncodeError: \'gbk\' codec can\'t encode character \'\ufffd\' in position 52: illegal multibyte sequence\r\n' 127.0.0.1 - - [23/Mar/2018 23:43:32] CGI script exit status 0x1

当您使用 print() 表达式时,Python 将字符串转换为字节,即。它 encode 使用默认编解码器。 这个默认值的选择取决于环境——在你的情况下它似乎是 GBK(从错误信息判断)。

在您的 CGI 脚本 HTML 页面中 returns,您将编解码器 ("charset") 指定为 UTF-8。 你当然可以把它改成GBK,但是它只能解决你的第一个问题(test.py的显示),不能解决第二个问题(test_form_action.py中的编码错误)。 相反,让 Python 在 STDOUT 上发送 UTF-8 编码数据可能更好。

一种方法是替换所有出现的

print(x)

sys.stdout.buffer.write(x.encode('utf8'))

或者,您可以将 sys.stdout 替换为 re-encoded 包装器,而不更改出现的 print()

sys.stdout = open(sys.stdout.buffer.fileno(), 'w', encoding='utf8'))

注意: 这两个解决方案在 Python 2.x 中不起作用(您必须省略那里的 .buffer 部分). 我写这篇文章是因为你的代码有 from __future__ import 语句,这些语句在 运行 和 Python 3 的代码中没有用处。