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 的代码中没有用处。
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 的代码中没有用处。