Ошибка Python Django "surrogates not allowed" при вызове model.save(), когда текст включает символ emoji

В настоящее время мы находимся в процессе создания системы, которая хранит текст в БД PostgreSQL через Django. Затем данные извлекаются через PGSync в ElasticSearch.

На данный момент мы столкнулись со следующей проблемой в тестовом примере

Сообщение об ошибке:

UnicodeEncodeError: 'utf-8' codec can't encode characters in position 159-160: surrogates not allowed

Мы определили символ, который вызывает эту проблему. Это эмодзи.

Сам текст представляет собой смесь греческих символов, "английских символов" и, как кажется, эмодзи. Греческий язык отображается не как греческий, а в форме \u.

Релевантный текст, вызывающий проблему:

\u03bc\u03b5 Some English Text \ud83d\ude9b\n#SomeHashTag

\ud83d\ude9b\ переводится как emoji: 🚛

Как написано здесь: https://python-list.python.narkive.com/aKjK4Jje/encoding-of-surrogate-code-points-to-utf-8

The definition of UTF-8 prohibits encoding character numbers
between U+D800 and U+DFFF, which are reserved for use with the
UTF-16 encoding form (as surrogate pairs) and do not directly
represent characters.

PostgreSQL имеет следующие кодировки:

  • По умолчанию:UTF8
  • Collate:en_US.utf8
  • Ctype:en_US.utf8

Это проблема utf8? Или специфическая для эмодзи? Это проблема django или postgresql?

Воспроизвести проблему:

x='\u03bc\u03b5 Some English Text \ud83d\ude9b\n#SomeHashTag'
print(x)

Traceback (последний последний вызов): Файл "", строка 1, в UnicodeEncodeError: 'utf-8' кодек не может кодировать символы в позиции 21-22: суррогаты не разрешены

Решение: примените кодеки raw_unicode_escape и unicode_escape (см. Python Specific Encodings) следующим образом:

y = x.encode('raw_unicode_escape').decode('unicode_escape').encode('utf-16_BE','surrogatepass').decode('utf-16_BE')
print(y)
με Some English Text 🚛
#SomeHashTag
Вернуться на верх