9

"TypeError: требуется объект, похожий на bytes, а не 'str' при обработке содержимого файла в Python 3"

5

Я недавно мигрировал на Python 3.5. Этот код работал корректно в Python 2.7:

with open(fname, 'rb') as f:
    lines = [x.strip() for x in f.readlines()]

for line in lines:
    tmp = line.strip().lower()
    if 'some-pattern' in tmp: continue
    # ... код

Однако в Python 3.5 на строке if 'some-pattern' in tmp: continue я получаю ошибку:

TypeError: a bytes-like object is required, not 'str'

Я не смог решить проблему, использовав .decode() с обеих сторон оператора in, а также не помогло применение следующего кода:

if tmp.find('some-pattern') != -1: continue

Что не так, и как мне это исправить?

5 ответ(ов)

8

Вы открыли файл в бинарном режиме:

with open(fname, 'rb') as f:

Это означает, что все данные, прочитанные из файла, возвращаются как объекты bytes, а не str. Поэтому вы не можете использовать строку в операторе проверки присутствия:

if 'some-pattern' in tmp: continue

Вместо этого вам нужно использовать объект bytes для проверки в tmp:

if b'some-pattern' in tmp: continue

Либо вы можете открыть файл как текстовый, заменив режим 'rb' на 'r'.

3

Вы можете закодировать вашу строку, используя метод .encode().

Пример:

'Hello World'.encode()

Как описано в сообщении об ошибке, чтобы записать строку в файл, вам необходимо сначала закодировать её в объект, подобный байтам, и метод encode() преобразует её в байтовую строку.

0

Как уже было упомянуто, вы открываете файл в бинарном режиме и затем создаете список байтов. В вашем последующем цикле for вы сравниваете строку с байтами, из-за чего код не работает.

Декодирование байтов во время добавления в список должно решить проблему. Измененный код будет выглядеть следующим образом:

with open(fname, 'rb') as f:
    lines = [x.decode('utf8').strip() for x in f.readlines()]

Тип bytes был введен в Python 3, и именно поэтому ваш код работал в Python 2. В Python 2 не существовало типа данных для байтов:

>>> s=bytes('hello')
>>> type(s)
<type 'str'>
0

Вам нужно использовать функцию encode() вместе с заданной строкой, заключённой в одинарные кавычки. Вот примеры использования этой функции:

Пример 1:

file.write(answers[i].encode() + b'\n')

В данном случае строка answers[i] сначала кодируется в байты с помощью encode(), а затем добавляется символ новой строки в байтовом формате с помощью префикса b.

Пример 2:

line.split(b' +++$+++ ')

Здесь мы вызываем метод split() на строке line, разделитель также заключён в байтовый литерал с префиксом b. Это позволит корректно разбирать строку, используя кодировку байтов.

0

Вам нужно помнить, что когда файл открыт в бинарном режиме, каждая строка будет представлять собой объект типа bytes, а не str. Это означает, что при попытке выполнить операцию проверки на наличие подстроки, вы столкнетесь с ошибкой TypeError: a bytes-like object is required, not 'str'.

Вот пример кода, который приведет к этой ошибке:

for line in lines:
    print(type(line))  # <class 'bytes'>
    if 'substring' in line:  # Здесь возникнет ошибка
       print('success')

Чтобы избежать этой ошибки, вам нужно декодировать объект bytes в строку с помощью метода decode(). Вот исправленный код:

for line in lines:
    line = line.decode()  # Декодируем строку из bytes в str
    print(type(line))  # <class 'str'>
    if 'substring' in line:  # Теперь это сработает правильно
       print('success')

Таким образом, после декодирования вы сможете успешно проверять наличие подстроки и избежать ошибок.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь