CALENDAR
Sun Mon Tue Wed Thu Fri Sat
     12
3456789
10111213141516
17181920212223
24252627282930
31      
<< December 2017 >>
本家STORY FACTサイト
NEW ENTRIES
CATEGORIES
RECENT COMMENTS
  • GB解析 -NG- 邪聖剣ネクロマンサー イシュメリアの悪夢 やったことあるんだよね・・・
    hikali (11/24)
  • GB解析 -NG- 邪聖剣ネクロマンサー イシュメリアの悪夢 やったことあるんだよね・・・
    マイケル村田 (11/21)
  • GB解析 -NG- 新・鬼ヶ島 暗黒の化身を討て! 成功した理由が良く分かりました。
    hikali (06/27)
  • GB解析 -NG- 新・鬼ヶ島 暗黒の化身を討て! 成功した理由が良く分かりました。
    マイケル村田 (06/24)
  • GB解析 -NG- ルパン三世/灼熱の監獄島 なかなかドラマチックなはなしなのだが・・・。
    hikali (06/23)
  • GB解析 -NG- ルパン三世/灼熱の監獄島 なかなかドラマチックなはなしなのだが・・・。
    マイケル村田 (06/20)
  • GB解析 -NG- トップをねらえ! 燃えろ! 国際マシーン兵器大会!! 戦闘大会・・・。
    hikali (05/21)
  • GB解析 -NG- トップをねらえ! 燃えろ! 国際マシーン兵器大会!! 戦闘大会・・・。
    マイケル村田 (05/17)
  •  『あらしにあこがれて』15
    hikali (05/02)
  •  『あらしにあこがれて』15
    hikali (05/02)
RECENT TRACKBACK
ARCHIVES
MOBILE
qrcode
LINKS
PROFILE
OTHERS
無料ブログ作成サービス JUGEM
 
管理人hikaliの開発の日々の備忘録です。
本家はこちら。
http://plaza.rakuten.co.jp/hikali/
<<  100%の仕事は最悪の無駄 | main |  ネタ放出エントリー −−国際産業クラスターの行方 >>
[Pythonゲーム修行]google app engine のユニコードの処理に苦しんだ方への処方箋
: 'ascii' codec can't encode characters in position 6-32: ordinal not in range(128)


 このエラーメッセージをみて、ハッと心を奪われた同士諸君、こんばんわ。そして、

: coercing to Unicode: need string or buffer, NoneType found


 このエラーメッセージを見るたびに悪夢のリフレインに苦しむ戦士のみなさま、ようこそおいでくださった。

 見果てぬ夢を胸に抱きながら、google app engineの独自仕様(と、Pythonの仕様でもあるのですが・・・)に打ち砕かれた日々も今日で終わる。
 今から、インドの奥地でわしが取得した奥義を伝授しよう!

 と、大げさに始めてみましたが、どうもここで苦しむ方が多い気がするので、わたしが四苦八苦してなんとか回避できるようになった方法をここに書いておきます。

 まずは、実際に、google app engineで動作することが確認されているコードから。


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

import cgi
import codecs

f = cgi.FieldStorage()


if f.getvalue('text','') == "":
html_body = u"""
ここにフォーム側htmlを記載
"""


print "Content-type: text/html¥n"

print html_body.encode('utf-8')

else:
html_body = u"""
ここに、表示側htmlを記載"""


text = f.getvalue('text','')
text = unicode(text,'utf-8')
text = text.replace("######","your name")

print "Content-type: text/html¥n"

print (html_body % text).encode('utf-8')


 (色分けには、こちらのスクリプトを使用しました)
 ■pyhighlight.py:Python ソースを HTML で色分け
 http://tuchinoko.moe-nifty.com/oboegaki/2005/05/pyhighlightpypy_932e.html


 Pythonのユニコード問題はこちら。
 ■PythonのUnicodeEncodeErrorを知る
 http://lab.hde.co.jp/2008/08/pythonunicodeencodeerror.html


 ■コードの全文はこちら
 html://story-fact.com/test10.txt


 ■実際に動いているところはこちら
 http://story-fact.appspot.com/


 google app engineのためにPythonを覚え始めたわたしような方は、ついphpのような言語と同じ感覚でPythonのコードを書いてしまいがちです。

 わたしがはまったのは、phpのechoと同じ感覚でPythonのprintを使ってしまっていたところ。phpのコードでは、htmlに文字列を埋め込む時にechoをよく使いますが、Pythonでは、これは通用しないと思った方がよいかもです。

  print (html_body % text).encode('utf-8')

 のように、埋め込んだ方がよいと思われます。
 これは、「PythonのUnicodeEncodeErrorを知る」に詳しいのですが、PythonのUnicodeの取り扱いが結構特殊だからです。また、Pythonはあまりマルチバイトの処理が得意ではないからです。phpのような感覚でいるとはまるかと思います。

 知っていた方が良さそうなのは、

 1.PythonのUnicodeは、いわゆるUTF-8ではない。

 純粋なUnicodeの方です。
 UTF-8の方は8バイト文字と呼ばれ、別の種類の文字列として区別されています。

 2.Pythonの内部では、マルチバイト文字列はUnicodeでないと処理できない。

 これも、知らないと結構はまるのですが(当然できるものと思い込んでいるため)、たとえば「+」を使って文字列を連結することもできません。ですので、フォームなどでマルチバイト文字列を受けとって加工するときは(置換など)、Unicodeに変換してやらなければなりません。

 3.Unicodeに変換するとき、値が空だとエラーになる。

 これも、嘘だろwww と思ったのですが、例外処理してやらなければなりません。

f = cgi.FieldStorage()
if f.getvalue('text','') != "":

 みたいな。

 4.google app engine ではUnicodeはprintしてはならない。

 これは、Pythonのprintが暗黙のうちに文字コードを変換するという仕様に絡むのですが、google app engineでは、必ずエラーとなります。

# -*- coding: utf-8 -*-

 のように文字コードを指定しても、google app engineではこのUnicode文字列をprintすると、asciiに変換しようとするからです。

 ですので、鉄則として、

 ・空を例外処理してマルチバイト文字列をUnicodeに変換
  ↓
 ・Unicode文字列で内部処理
  ↓
 ・マルチバイト文字列にエンコードして、print

 という流れになります。

 以上、簡単ですが、勘所を書いておきました。
 少しでも助けになれば幸いです。
 わたしも何度も挫折しそうになりましたが(^_^; これを機にすてきなアプリケーションを作ってくださいね!

 PS.

 これ、一つ一つ理解するのに、それぞれ5時間ぐらいかかったよ・・・。とほほ・・・。

| pythonゲーム修行 | 22:18 | comments(6) | trackbacks(0) | 昨年の記事
>>> unicode("")
u''
>>> u""
u''
>>> "".decode()
u''

なんの問題も発生しませんが、Noneをunicode文字列にしようとしましたか?
| aodag | 2008/11/18 9:37 PM |
こんばんわ!
コメントありがとうございます!

> なんの問題も発生しませんが、Noneをunicode文字列にしようとしましたか?

 えーと、説明不足で申し訳ないです。
 これはたぶんgoogle app engineの仕様かと思います。ですので、Pythonのコマンドラインでは問題は発生しないと思います。
| hikali | 2008/11/19 9:53 PM |
こんばんわ。

私もようやくこれらのエラーの原因の理解が前進しました。

> Noneをunicode文字列にしようとしましたか?

こればポイントのケースがありますので

 try:
entry.title.text = unicode(entry.title.text,'utf-8').encode('Shift_JIS')
except:
のようなことで回避できることがあります。

| kwin | 2009/02/04 12:07 AM |
こんばんわ。
コメントありがとうございます。

>こればポイントのケースがありますので

> try:
>entry.title.text = unicode(entry.title.text,'utf-8').encode('Shift_JIS')
>except:
>のようなことで回避できることがあります。

 ありがとうございます(^_^;
 あとになって、あれ? 例外処理すればいいじゃね? と気付きました・・・(<だめすぎwww)。

 Google App EngineはPythonの仕様とGAEの仕様がごっちゃになっていて、ほんと大変ですね(^_^; 現在脱落中ですが、またそのうち復帰したいです。
| hikali | 2009/02/04 9:27 PM |
参考にさせて頂きました。どうもありがとうございました。
| ike | 2010/03/23 9:46 PM |
すげー参考になりました!!
| yuki777 | 2010/05/17 3:15 AM |









http://blog.story-fact.com/trackback/970842