2013-02-13 128 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