Python 3.4: str: AttributeError: объект' str ' не имеет атрибута 'decode
У меня есть эта кодовая часть функции, которая заменяет плохо закодированные внешние символы из строки:
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]. Работает, но очень некрасиво, и я хотел бы это понять. поведение)
Заранее спасибо !
Редактировать:
Pypyodbc в python3 использует все unicode по умолчанию. Это меня смутило. При подключении вы можете сказать ему, чтобы он использовал ANSI.
con_odbc = pypyodbc.connect("DSN=GP", False, False, 0, False)
Затем я могу преобразовать возвращенные материалы в cp850, который является начальной кодовой страницей базы данных.
str(odbc_str, "cp850", "replace")
Больше нет необходимости вручную заменять каждый специальный символ. Большое спасибо pepr
1 ответ:
Напечатанное
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__()
, который является "неформальным" или хорошо печатаемым строковым представлением объекта. Для объектов string это сама строка. Если объект не имеет метода__str__()
, затемstr()
возвращается к возвращениюrepr(object)
.b"
на самом деле являются двумя символами, которые являются частью содержимого строки. Вы также можете попробовать: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
из базы данных (если это возможно) и исправить байты (см. байты.переводить 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, что такое правильная кодировка.) Затем вы хотите кодировать строку обратно в байты, используя этунеправильную кодировку, а затем декодировать байты, используяправильную кодировку.