2009-06-08 11 views
8

私はUnicodeからの変換に問題があることは知っていますが、どこで起こっているのか分かりません。SQLAlchemyのUnicode問題

最近のEruopean旅行に関するデータをHTMLファイルのディレクトリから抽出しています。ロケーション名の一部に非ASCII文字(é、ô、üなど)が含まれています。私は正規表現を使用してファイルの文字列表現からデータを取得しています。

私はそれらを見つけると私は場所を印刷する場合のエンコードがOKでなければならないので、彼らは文字で印刷:

Le Pré-Saint-Gervais, France 
Hôtel-de-Ville, France 

私はSQLAlchemyのを使用してSQLiteのテーブルにデータを格納しています:

Base = declarative_base() 
class Point(Base): 
    __tablename__ = 'points' 

    id = Column(Integer, primary_key=True) 
    pdate = Column(Date) 
    ptime = Column(Time) 
    location = Column(Unicode(32)) 
    weather = Column(String(16)) 
    high = Column(Float) 
    low = Column(Float) 
    lat = Column(String(16)) 
    lon = Column(String(16)) 
    image = Column(String(64)) 
    caption = Column(String(64)) 

    def __init__(self, filename, pdate, ptime, location, weather, high, low, lat, lon, image, caption): 
     self.filename = filename 
     self.pdate = pdate 
     self.ptime = ptime 
     self.location = location 
     self.weather = weather 
     self.high = high 
     self.low = low 
     self.lat = lat 
     self.lon = lon 
     self.image = image 
     self.caption = caption 

    def __repr__(self): 
     return "<Point('%s','%s','%s')>" % (self.filename, self.pdate, self.ptime) 

engine = create_engine('sqlite:///:memory:', echo=False) 
Base.metadata.create_all(engine) 
Session = sessionmaker(bind = engine) 
session = Session() 

Iファイルをループし、データベースにそれぞれ1からのデータを挿入します。

for filename in filelist: 

    # open the file and extract the information using regex such as: 
    location_re = re.compile("<h2>(.*)</h2>",re.M) 
    # extract other data 

    newpoint = Point(filename, pdate, ptime, location, weather, high, low, lat, lon, image, caption) 
    session.add(newpoint) 
    session.commit() 

私はそれぞれのインサートに次の警告を参照してください。

/usr/lib/python2.5/site-packages/SQLAlchemy-0.5.4p2-py2.5.egg/sqlalchemy/engine/default.py:230: SAWarning: Unicode type received non-unicode bind param value 'Spitalfields, United Kingdom' 
    param.append(processors[key](compiled_params[key])) 

をそして、私のようなテーブルで何かをしようとすると:

session.query(Point).all() 

私が手:

Traceback (most recent call last): 
    File "./extract_trips.py", line 131, in <module> 
    session.query(Point).all() 
    File "/usr/lib/python2.5/site-packages/SQLAlchemy-0.5.4p2-py2.5.egg/sqlalchemy/orm/query.py", line 1193, in all 
    return list(self) 
    File "/usr/lib/python2.5/site-packages/SQLAlchemy-0.5.4p2-py2.5.egg/sqlalchemy/orm/query.py", line 1341, in instances 
    fetch = cursor.fetchall() 
    File "/usr/lib/python2.5/site-packages/SQLAlchemy-0.5.4p2-py2.5.egg/sqlalchemy/engine/base.py", line 1642, in fetchall 
    self.connection._handle_dbapi_exception(e, None, None, self.cursor, self.context) 
    File "/usr/lib/python2.5/site-packages/SQLAlchemy-0.5.4p2-py2.5.egg/sqlalchemy/engine/base.py", line 931, in _handle_dbapi_exception 
    raise exc.DBAPIError.instance(statement, parameters, e, connection_invalidated=is_disconnect) 
sqlalchemy.exc.OperationalError: (OperationalError) Could not decode to UTF-8 column 'points_location' with text 'Le Pré-Saint-Gervais, France' None None 

私は希望元の文字がそのまま残っている場所名を正しく保存して戻すことができます。どんな助けでも大歓迎です。

答えて

11

私は多少私の悩みを説明する助け、この記事を見つけました次の:

ファイルを開くとき:

infile = codecs.open(filename, 'r', encoding='iso-8859-1') 

場所を印刷:

print location.encode('ISO-8859-1') 

を私は今、前からのエラーなしのテーブルからデータを照会し、操作することができます。私は、テキストを出力するときにエンコーディングを指定するだけです。

は(私はまだ完全にこれがそう、私はそれはPythonのUnicodeの扱いについての詳細を学ぶための時間だと思う働いているかを理解していない...)

+1

"iso-8859-1"の前に "cp1252"を最初に試してみます。そして、私は次のことがまったく役立つかどうかわからない:http://stackoverflow.com/questions/368805/python-unicodedecodeerror-am-i-misunderstanding-encode/370199#370199 – tzot

7

Unicode列のUnicodeではなく、文字列の列タイプを使用してみてください:

Base = declarative_base() 
class Point(Base): 
    __tablename__ = 'points' 

    id = Column(Integer, primary_key=True) 
    pdate = Column(Date) 
    ptime = Column(Time) 
    location = Column(Unicode(32)) 
    weather = Column(String(16)) 
    high = Column(Float) 
    low = Column(Float) 
    lat = Column(String(16)) 
    lon = Column(String(16)) 
    image = Column(String(64)) 
    caption = Column(String(64)) 

編集:コメントへの応答:

あなたがUnicodeのエンコーディングに関する警告を取得している場合は、2つのものがあります試してみることができます:

  1. あなたの場所をユニコードに変換してください。

    newpoint =ポイント(ファイル名、pdate、PTIME、ユニコード(場所)、天候、高、低、緯度、経度、画像、キャプション)

    Unicode変換:これはあなたのポイントは次のように作成した意味します文字列またはUnicode文字列のいずれかを渡すとUnicode文字列が生成されるので、何を渡すか心配する必要はありません。

  2. これで解決できない場合は、unicodeオブジェクト。これは、次のようなコードを使用することを意味します:

    newpoint =ポイント(ファイル名、pdate、ptime、ユニコード(エンコード)、天気、高低、緯度、経度、画像、キャプション)

    この手順はおそらく必要ありませんが、基本的にはユニコードオブジェクトをユニコードコードポイントから特定のバイト表現(この場合はutf-8)に変換します。私はユニコードオブジェクトを渡すときにSQLAlchemyがこれを行うと期待しますが、そうでないかもしれません。sqlalchemy.orgから

+0

は提案をいただき、ありがとうございます。私はこれが正しい方向に向かっていると思う。私は今私が挿入しているデータのエンコーディングについての警告を取得していますが、これを修正する方法がわかりません。私はあなたの提案を反映するために私の質問を更新しました。 –

7

参照してください0.4.2

は、文字列と create_engine()、 アサート_UNICODEに新しいフラグを追加=(TRUE | FALSE | '警告' |なし) 。 FalseまたはNoneのデフォルト値は です。Unicodeタイプの_endine()およびString、'warn'を作成します。 Trueの場合、 の非ユニコード・バイト・テストがバインド・パラメータとして渡された場合、すべてのユニコード変換操作では、 例外が発生します。 '警告'の結果は です。すべてのユニコード対応の アプリケーション は、正確にデータが往復するように、Pythonのユニコードオブジェクト(つまり、uhhello 'で、 ' hello 'ではない)を適切に使用することを強くお勧めします。

私はあなたが非ユニコードのバイトテストを入力しようとしていると思います。おそらく、これは正しい軌道上であなたを導くかもしれませんか? 'hello'とu'hello 'を比較すると、変換の形式が必要です。私は「コーデック」モジュールを使用することによって、所望の結果を得ることができたし、その後のように私のプログラムを変更する

http://www.amk.ca/python/howto/unicode#reading-and-writing-unicode-data

乾杯