Квалификацию надо иногда повышать, и вообще учиться для мозгов полезно. А потому пошел я недавно на курсы - поизучать Python и всякие его фреймворки. На днях вот до Django добрался. И тут мы в ходе обучения коллективно выловили не то чтобы баг, но дивный эффект на стыке Python 3, Sqlite 3, JSON и Win 10. Причем эффект был настолько дивен, что гугль нам не помог - пришлось собираться всей заинтересованной группой вместе с преподавателем и коллективным разумом его решать.
А дело вот в чем: изучали мы базу данных (а у Django предустановлена Sqlite 3) и, чтоб каждый раз заново руками данные не вбивать, прикрутили загрузку скриптом из json-файлов. А в файлы данные из базы штатно дампили питоновскими же методами:
python manage.py dumpdata -e contenttypes -o db.json
Внезапно те, кто работал под виндой (за все версии не поручусь, у нас подобрались только обитатели Win 10), обнаружили, что дамп у них производится в кодировке windows-1251. Более того, джейсоны в этой кодировке отлично скармливаются базе. Но стоило только переформатировать их в штатную по документам для Sqlite 3, Python 3 и особенно для JSON кодировку UTF-8, как в лучшем случае кириллица в базе превращалась в тыкву, а в худшем ломался вообще весь процесс загрузки данных.
Ничего подобного найти не удалось ни в документации, ни во всем остальном гугле, считая и англоязычный. Что самое загадочное, ручная загрузка тех же самых данных через консоль или админку проекта работала как часы, хотя уж там-то кодировка была точно UTF-8. Более того, принудительное прописывание кодировки базе никакого эффекта не дало.
Мы предположили, что причиной эффекта было взаимодействие джейсона с операционной системой - каким-то образом при записи и чтении именно джейсонов система навязывала свою родную кодировку вместо нормальной. И действительно, когда при открытии файла принудительно устанавливалась кодировка UTF-8:
open(os.path.join(JSON_PATH, file_name + '.json'), 'r', encoding="utf-8")
в базу попадали не кракозябры, а нормальные русские буквы. Но проблему с созданием дампа таким способом не решишь, а переделывать кодировку потом руками тоже как-то не по-нашему.
И тогда мы решили поискать способ укротить винду.
И такой способ нашелся. Вот он:
открываем панель управления, но не новую красивую, а старую добрую:
открываем (по стрелке) окошко региона:
по стрелкам переключаем вкладку "Дополнительно" и открываем окошко "Изменить язык системы":
и в нем ставим галку по стрелке в чекбоксе "Бета-версия: Использовать Юникод (UTF-8) для поддержки языка во всем мире.
Система потребует перезагрузки, после чего проблема будет решена.
Не могу сказать, чтобы этот мелкий странный баг был так уж важен или интересен (питоновские проекты обычно живут под линуксами, где такого не бывает), но мозги он нам поломал изрядно - вследствие чего я и решил написать эту заметку. Мало ли кто еще из новичков как раз во время учебы попадется.
Sm1le291
Серьёзно? А причём здесь Windows 10? Вам на стэковерфлоу надо было с вашей находкой
true_Jorian Автор
При том, что эффект пойман только на Вин10 и решился средствами Вин10 же.
qw1
Ну здорово. А другой софт требует, чтобы в этом месте стояла кодировка 1251. И что, каждый раз менять и перезагружаться?
13werwolf13
давно винду в глаза не видел, но предположу что эта галочка добавляет поддержку utf-8 но не ломает уже работающую 1251
qw1
В винде есть Unicode API (приминающее строки в UTF-16) и ANSI API (работающее со строками в 1-байтных кодировках), кодировка последнего настраивается под региональный стандарт, например, 1251 для русской локализации. Галочка делает так, чтобы ANSI API работало со строками UTF-8
aamonster
Интересно, много ли такого «другого софта» осталось. Уже много лет не доводилось в винде руками прописывать кодировку для non-unicode софта (что когда-то было нормой).
qw1
Не доводилось прописывать, потому что винда научилась её сама ставить вместе с языком. А софта дофига. Например, весь, скомпилированный старыми версиями Delphi.
Да и новый софт начинающие Windows программисты C/C++ не торопятся писать под unicode, ведь это везде wchar_t, а в древнючих учебниках, с которых копипастят примеры, сплошной char для строк. Только уже опытные, которые понимают зачем все эти вещи, пишут где надо char, где надо — wchar_t, где надо — конвертируют из однобайтной кодировки в utf-16.
alex-khv
Если софт хоть сколько-нибудь общается со сторонними источники данных, то там практически везде utf.
И для однообразия проще везде использовать wchar_t.
qw1
В первом пункте вы про какой utf пишете, про utf-8?
А wchar_t вообще platform-specific, может быть как 16-битным, так и 32-битным, но точно отличается от utf-8. Так что, в C/C++ однообразие нам, к сожалению, не светит.
lab412
у меня Win10 и такой галочки нет. экспериментальная фунцкия.
в итоге проблема не решена. вы её решили лично на вашем компьютере в вашей комнате. для других решение не подходит…
true_Jorian Автор
У нас в группе около десятка человек этим решением успешно воспользовались — так что насчет «лично» вы ошибаетесь. Более того, тут в комментах есть ссылка на обсуждение аналогичной проблемы разработчиками Джанго, где точно такую же рекомендацию давали для Вин8.1 — так что и там эта галочка уже была.
Но я допускаю, что не сумел охватить все возможные ситуации.
mistergrim
Для тех, у кого актуальная версия Windows, вполне подходит.