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 5

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, что такое правильная кодировка.) Затем вы хотите кодировать строку обратно в байты, используя этунеправильную кодировку, а затем декодировать байты, используяправильную кодировку.