Python CGI - UTF-8无效

6 投票
2 回答
6300 浏览
提问于 2025-04-17 15:47

关于HTML5和Python CGI:

如果我写了UTF-8的Meta标签,我的代码就不管用了。
如果我不写这个标签,它就能正常工作。

页面的编码是UTF-8。

print("Content-type:text/html")
print()
print("""
    <!doctype html>
    <html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        şöğıçü
    </body>
    </html>
""")

这段代码不管用。

print("Content-type:text/html")
    print()
    print("""
        <!doctype html>
        <html>
        <head></head>
        <body>
            şöğıçü
        </body>
        </html>
    """)

但是这段代码能正常工作。

2 个回答

10

来自 https://ru.stackoverflow.com/a/352838/11350

首先,别忘了在文件中设置编码。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

然后试试这个。

import sys
import codecs

sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())

或者如果你使用的是apache2,可以把这个添加到你的配置文件中。

AddDefaultCharset UTF-8    
SetEnv PYTHONIOENCODING utf8
10

在使用CGI的时候,调用 print() 函数需要确保输出的编码设置正确。print() 是往 sys.stdout 这个地方写东西,而 sys.stdout 是用特定的编码打开的,这种编码的选择跟你使用的操作系统有关,而且还可能因为脚本的运行方式不同而有所不同。当你把脚本作为CGI脚本运行时,你几乎无法知道会用什么编码。

在你的情况中,网络服务器已经把文本输出的编码设置成了固定的编码,而不是UTF-8。Python会根据这个设置来输出内容。如果没有 <meta> 头,浏览器会正确地猜测这个编码(或者服务器在Content-Type头中告诉了它),但如果有了 <meta> 头,你就告诉浏览器使用一个不同的编码,而这个编码对于生成的数据来说是不正确的。

你可以直接写入 sys.stdout.buffer,但要先把内容编码成UTF-8。可以写一个辅助函数来简化这个过程:

import sys

def enc_print(string='', encoding='utf8'):
    sys.stdout.buffer.write(string.encode(encoding) + b'\n')

enc_print("Content-type:text/html")
enc_print()
enc_print("""
    <!doctype html>
    <html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        şöğıçü
    </body>
    </html>
""")

另一种方法是用一个新的 io.TextIOWrapper() 对象 来替换 sys.stdout,这个新对象使用你需要的编码:

import sys
import io

def set_output_encoding(codec, errors='strict'):
    sys.stdout = io.TextIOWrapper(
        sys.stdout.detach(), errors=errors,
        line_buffering=sys.stdout.line_buffering)

set_output_encoding('utf8')

print("Content-type:text/html")
print()
print("""
    <!doctype html>
    <html>
    <head></head>
    <body>
        şöğıçü
    </body>
    </html>
""")

撰写回答