2014-09-19 99 views
0

使用下面的代碼(PHP)我發送一個字符串到Python程序:如何解碼unicode python參數?

shell_exec("python3 /var/www/html/app.py \"$text\""); 

$text變量包含非英文字符串。問題是,當我打印在Python的論點print(sys.argv)我得到這樣一個結果:

['/var/www/html/app.py', '\udcd8\udca8\udcd8\udcaa\udcd8\udcb5\udcd8\udcb4\udcda\udca9 \udcd8\udcae\udcd8\udcab\udcd9\udc87\udcd8\udca8 \udcd8\udcaa\udcd8\udcb4\udcd8\udcb5\udcd8\udcab'] 

我怎麼這個unicode字符串轉換爲蟒文字的原始形式?

+0

你期望的輸出?這些碼點是代理。 – geoffspear 2014-09-19 17:20:03

+0

@Wooble我想在一個使用普通字符串而不是unicodes的函數中使用這個文本。 – hpn 2014-09-19 18:01:42

回答

2

Python使用您的LOC ale的編碼來解碼從命令行獲取的字節。默認的C語言環境使用ascii。它似乎在utf-8中似乎是$text。因此,Python必須使用surrogateescape錯誤處理程序將這些字節解碼爲文字sys.argv[1],這會產生您在輸出中看到的單獨替代項,例如'\udcd8'

你可以使用UTF-8碼例如,LC_ALL=C.UTF-8或手動重新編碼的參數:sys.argv[1].encode(locale.getpreferredencoding(True), 'surrogateescape').decode('utf-8')

>>> s = u'\udcd8\udca8\udcd8\udcaa\udcd8\udcb5\udcd8\udcb4\udcda\udca9 \udcd8\udcae\udcd8\udcab\udcd9\udc87\udcd8\udca8 \udcd8\udcaa\udcd8\udcb4\udcd8\udcb5\udcd8\udcab' 
>>> print(s.encode('ascii', 'surrogateescape').decode('utf-8')) 
بتصشک خثهب تشصث 
+0

手動重新編碼參數時出現此錯誤:'UnicodeEncodeError:'ascii'編解碼器無法編碼0-5位置的字符:序號不在範圍內(128)' – hpn 2014-09-20 18:45:49

+0

@hpn:我已經添加了代碼示例,沒有錯誤 – jfs 2014-09-21 04:28:13

2
shell_exec("python3 /var/www/html/app.py \"$text\""); 

(我希望$text強烈消毒,逃了出來,或靜!如果用戶輸入了在這裏你有一個可怕的遠程執行代碼漏洞!)

'\udcd8\udca8\udcd8\udcaa\udcd8\udcb5\udcd8... 

確定什麼曾經發生在這裏PHP已經向Python傳遞了UTF-8編碼的字符串,但Python不知道命令行輸入是UTF-8。 (通常當你將Python作爲命令運行時,它可以從你的終端運行,但是當它運行在web服務器中的Python時,沒有終端。)

不知道輸入是什麼,默認爲純ASCII 。輸入中的高字節在ASCII中無效,但Python 3對無效字節有一個「surrogateescape」回退處理程序,將其解碼爲Unicode字符串時應用於命令行。這會產生無效的UTF-16替代碼單元U + DC80-U + DCFF,但至少可以讓原始高字節在需要時恢復。

因此,要麼:

  • PYTHONIOENCODING環境變量設置爲UTF-8執行Python之前,因此它知道正確的編碼是擺在首位的,或者

  • 變化的Python腳本預 - 流程的輸入與恢復正確的輸入sys.argv[1].encode('utf-8', 'surrogateescape').decode('utf-8')

+0

'PYTHONIOENCODING'對'sys.argv'沒有影響。您應該使用*相同的*字符編碼來編碼(不要硬編碼「utf-8」),正如Python用來解碼'sys.argv'一樣。 – jfs 2014-09-20 05:59:25

+0

@bobince +1並感謝您的警告!將PYTHONENCODING設置爲utf-8不起作用,但是'LANG = en_US.utf-8'工作 – hpn 2014-09-20 18:50:27