web-dev-qa-db-ja.com

Python 3.4:str:AttributeError: 'str'オブジェクトに属性がありません 'デコード

文字列から正しくエンコードされていない外部文字を置き換える関数のこのコード部分があります:

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'
  • ここでsがバイトである理由を知っていますか?
  • なぜそれを実際の文字列にデコードできないのですか?
  • あなたはそれをきれいな方法で行う方法を知っていますか? (今日はs [2:] [:-1]を返します。動作していますが非常に醜いので、この動作を理解したいと思います)

前もって感謝します !

編集:

python3のpypyodbcは、デフォルトですべてのユニコードを使用します。それは私を混乱させました。接続時に、ANSIを使用するように彼に指示できます。

con_odbc = pypyodbc.connect("DSN=GP", False, False, 0, False)

次に、返されたものをデータベースの最初のコードページであるcp850に変換できます。

str(odbc_str, "cp850", "replace")

各特殊文字を手動で置き換える必要はもうありません。どうもありがとうございました

7
Romu

印刷された_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を使用してバイトをデコードします)エンコーディング。

3
pepr