2013-02-13 125 views
3

对于HTML5和Python CGI:Python CGI - UTF-8不工作

如果我编写UTF-8元标记,我的代码不起作用。 如果我不写,它的作品。

页面编码是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> 
    """) 

但是这个代码的作品。

+1

您是否指定了源编码?编辑器保存的文件是什么编码? Python发送你输入的字符串*真正*所以如果你用Latin-1编码保存了这个文件,这就是发送的内容。 – 2013-02-13 18:07:30

+0

文件编码:utf-8。通常,它的工作原理。我以前的项目工作。我使用Python3.3。它的默认编码是utf8。顺便说一句,我不会说英语。有时我不明白 – user1898723 2013-02-13 18:23:52

+0

啊哈,这是重要的信息!在这种情况下,你需要明确编码。 – 2013-02-13 18:25:47

回答

7

对于CGI,使用print()要求正确的编解码器已被设置为输出。 print()写入sys.stdoutsys.stdout已打开具有特定编码,以及如何确定取决于平台可以根据脚本的运行方式而有所不同。将脚本作为CGI脚本运行意味着您几乎不知道将使用哪种编码。

就你而言,Web服务器已经将文本输出的区域设置为除UTF-8以外的固定编码。 Python使用该区域设置以该编码产生输出,并且没有<meta>标题,浏览器正确地猜测该编码(或者服务器已经在Content-Type标题中传达它),但是使用<meta>标题告诉它使用一种不同的编码,一种对生成的数据不正确。

在明确编码为UTF-8之后,您可以直接写入sys.stdout.buffer。做一个辅助函数来简化这一过程:

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() object更换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> 
""") 
+0

这真的很不错,但从我在文档中看到的情况来看,这也可能取决于实现! '这不是TextIOBase API的一部分,并且可能不存在于某些实现中(来自http://docs.python.org/3/library/io.html) – Zenon 2013-02-13 23:43:10

+0

@Zenon:这可能确实适用于某些实现(特别是'StringIO'),但是'stdout'流肯定有'.buffer'属性;这是记录在[[sys.stdout'文档](http://docs.python.org/3/library/sys.html#sys.stdout))。 – 2013-02-13 23:56:01

+1

在python3.4中不起作用,发生“内部服务器错误” – alireza 2015-01-06 19:39:39

6

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,添加到您的conf。

AddDefaultCharset UTF-8  
SetEnv PYTHONIOENCODING utf8 
+1

当所有其他都不适用时有效。但是,我们不得不去做这种无稽之谈来做这么基本的事情,这不是荒谬的吗? – havlock 2017-11-25 17:18:01