文字列から正しくエンコードされていない外部文字を置き換える関数のこのコード部分があります:
s = "String from an old database with weird mixed encodings"
s = str(bytes(odbc_str.strip(), 'cp1252'))
s = s.replace('\\x82', 'é')
s = s.replace('\\x8a', 'è')
(...)
print(s)
# b"String from an old database with weird mixed encodings"
ここでは、バイトではなく「実際の」文字列が必要です。しかし、それらをデコードしたいときは、例外があります:
s = "String from an old database with weird mixed encodings"
s = str(bytes(odbc_str.strip(), 'cp1252'))
s = s.replace('\\x82', 'é')
s = s.replace('\\x8a', 'è')
(...)
print(s.decode("utf-8"))
# AttributeError: 'str' object has no attribute 'decode'
前もって感謝します !
編集:
python3のpypyodbcは、デフォルトですべてのユニコードを使用します。それは私を混乱させました。接続時に、ANSIを使用するように彼に指示できます。
con_odbc = pypyodbc.connect("DSN=GP", False, False, 0, False)
次に、返されたものをデータベースの最初のコードページであるcp850に変換できます。
str(odbc_str, "cp850", "replace")
各特殊文字を手動で置き換える必要はもうありません。どうもありがとうございました
印刷された_b"String from an old database with weird mixed encodings"
_は、文字列の内容を表したものではありません。文字列の内容の値です。エンコーディング引数をstr()
...に渡さなかったため(ドキュメントを参照 https://docs.python.org/3.4/library/stdtypes.html#str )
エンコーディングもエラーも指定されていない場合、
str(object)
はobject.__str__()
を返します。これは、オブジェクトの「非公式」または印刷可能な文字列表現です。文字列オブジェクトの場合、これは文字列自体です。オブジェクトに__str__()
メソッドがない場合、str()
はフォールバックしてrepr(object)
を返します。
これがあなたの場合に起こったことです。 _b"
_は、実際には文字列コンテンツの一部である2文字です。次のことも試すことができます。
_s1 = 'String from an old database with weird mixed encodings'
print(type(s1), repr(s1))
by = bytes(s1, 'cp1252')
print(type(by), repr(by))
s2 = str(by)
print(type(s2), repr(s2))
_
そしてそれは印刷します:
_<class 'str'> 'String from an old database with weird mixed encodings'
<class 'bytes'> b'String from an old database with weird mixed encodings'
<class 'str'> "b'String from an old database with weird mixed encodings'"
_
これが_s[2:][:-1]
_があなたのために働く理由です。
それについてもっと考えるなら、(私の意見では)またはデータベースからbytes
またはbytearray
を取得し(可能であれば)、バイトを修正したい(bytes.translate-を参照) https://docs.python.org/3.4/library/stdtypes.html?highlight=translate#bytes.translate )または、文字列を正常に取得できます(その文字列を作成するときに例外がなかったのは幸運です) )、間違った文字を正しい文字に置き換えたい(str.translate()
https://docs.python.org/3.4/library/stdtypes.html?highlight=translate#も参照) str.translate )。
おそらく、ODBCは内部的に間違ったエンコーディングを使用していました。 (つまり、データベースの内容は正しい可能性がありますが、ODBCによって誤って解釈されており、ODBCに正しいエンコードを伝えることができません。)次に、文字列をエンコードし直します。そのwrongエンコーディングを使用してバイトに変換し、rightを使用してバイトをデコードします)エンコーディング。