TypeError: невозможно использовать строковый шаблон на байтоподобном объекте python3
Я обновил свой проект до Python 3.7 и Django 3.0
Вот код models.py
def get_fields(self):
fields = []
html_text = self.html_file.read()
self.html_file.seek(0)
# for now just find singleline, multiline, img editable
# may put repeater in there later (!!)
for m in re.findall("(<(singleline|multiline|img editable)[^>]*>)", html_text):
# m is ('<img editable="true" label="Image" class="w300" width="300" border="0">', 'img editable')
# or similar
# first is full tag, second is tag type
# append as a list
# MUST also save value in here
data = {'tag':m[0], 'type':m[1], 'label':'', 'value':None}
title_list = re.findall("label\s*=\s*\"([^\"]*)", m[0])
if(len(title_list) == 1):
data['label'] = title_list[0]
# store the data
fields.append(data)
return fields
Вот трассировка моей ошибки
File "/home/harika/krishna test/dev-1.8/mcam/server/mcam/emails/models.py", line 91, in get_fields
for m in re.findall("(<(singleline|multiline|img editable)[^>]*>)", html_text):
File "/usr/lib/python3.7/re.py", line 225, in findall
return _compile(pattern, flags).findall(string)
TypeError: cannot use a string pattern on a bytes-like object
Как я могу решить свою проблему
Дело в том, что в python3 read возвращает байты (т.е. "сырое" представление), а не string. Вы можете конвертировать между байтами и строкой, если укажете кодировку, т.е. как символы конвертируются в байты:
>>> '☺'.encode('utf8')
b'\xe2\x98\xba'
>>> '☺'.encode('utf16')
b'\xff\xfe:&'
префикс b перед строкой означает, что значение не string, а bytes. Вы также можете передавать необработанные байты, если используете этот префикс:
>>> bytes_x = b'x'
>>> string_x = 'x'
>>> bytes_x == string_x
False
>>> bytes_x.decode('ascii') == string_x
True
>>> bytes_x == string_x.encode('ascii')
True
Обратите внимание, что вы можете использовать только основные (ASCII) символы, если вы используете префикс b:
>>> b'☺'
File "<stdin>", line 1
SyntaxError: bytes can only contain ASCII literal characters.
Итак, чтобы решить вашу проблему, вам нужно либо преобразовать входные данные в строку с соответствующей кодировкой:
html_text = self.html_file.read().decode('utf-8') # or 'ascii' or something else
Или - возможно, лучший вариант - использовать bytes в findall вместо строк:
for m in re.findall(b"(<(singleline|multiline|img editable)[^>]*>)", html_text):
...
title_list = re.findall(b"label\s*=\s*\"([^\"]*)", m[0])
(обратите внимание на b перед каждой "строкой")