Несовместимое с Python хранение специальных символов в строке - PullRequest
1 голос
/ 25 июня 2019

Версия Python 3.7. Я только что обнаружил, что python иногда будет хранить символ - в строке с несколькими представлениями, и я совершенно не понимаю, почему и как с этим бороться.

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

У меня есть две строки, s1 и s2 обе равны 'Dan Peña'

Они оба имеют тип string.

Я могу запустить код:

print(s1 == s2) # prints false
print(len(s1)) # prints 8
print(len(s2)) # prints 9
print(type(s1)) # print 'str'
print(type(s2)) # print 'str'
for i in range(len(s1)):
    print(s1[i] + ", " + s2[i])

Вывод цикла будет:

D, D
a, a
n, n
 ,  
P, P
e, e
ñ, n
a, ~

Итак, существуют ли какие-либо методы python для работы с этими несоответствиями или, по крайней мере, есть некоторая спецификация относительно того, когда python будет использовать какое представление?

Было бы также неплохо узнать, почему Python решил реализовать этот способ.

Edit:

Одна строка извлекается из базы данных django, а другая строка - из строки, полученной в результате анализа имени файла из вызова списка dir.

from app.models import Model
from django.core.management.base import BaseCommand

class Command(BaseCommand):

    def handle(self, *args, **kwargs):
        load_dir = "load_dir_name"
        save_dir = "save_dir"

        files = listdir(load_dir)
        save_file_map = {file[:file.index("_thumbnail.jpg")]: f"{save_dir}/{file}" for file in files}
        for obj in Model.objects.all():
            s1 = obj.title
            save_file_path = save_file_map[s1] # Key error when encountering ñ.

Однако, когда я ищу через диктовку save_file_map, я нахожу ключ, точно такой же, как s1, за исключением того, что ñ кодируется как символы n~, а не как символ ñ.

Обратите внимание, что файлы, которые я загружаю в приведенном выше коде с помощью списка dir, в первую очередь называются в поле obj.title с именем base, поэтому следует убедиться, что файл с именем находится в каталоге load_dir.

1 Ответ

5 голосов
/ 25 июня 2019

Вы хотите нормализовать строки, чтобы использовать то же представление.Прямо сейчас, один из них использует символ n + символ тильды (2 знака), а другой использует один символ, представляющий n с тильдой.

unicodedata.normalize должен делать то, что выхочу.См. Документы здесь .

Вы можете назвать это так: unicodedata.normalize('NFC', s1).'NFC' говорит unicodedata.normalize, что вы хотите использовать составные формы для всего, например, версия с 1 символом .В документах есть и другие опции, кроме 'NFC', какой из них вы используете полностью.

Теперь, в какой момент вы нормализуете, зависит от вас (я не знаю, как ваше приложениеструктурированная).Например, вы можете нормализовать перед вставкой в ​​базу данных или нормализовать каждый раз, когда читаете из базы данных.

...