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 перед каждой "строкой")

Вернуться на верх