Как заставить Python 3 правильно обрабатывать строки Unicode из MongoDB?

Я использую 64-разрядную версию Windows 7, Python 3, MongoDB и PyMongo. Я знаю, что в Python 3 все строки имеют юникод. Я также знаю, что MongoDB хранит все строки в формате unicode. Поэтому я не понимаю, почему, когда я извлекаю документ из своей базы данных, где значением определенного поля является «C:\Some Folder\E=mc².xyz», Python обрабатывает эту строку как «C:\Some Folder\ E=mc².xyz". Он не просто печатает таким образом; os.path.exists() возвращает False. Теперь, как будто это недостаточно запутанно, если я сохраню строку в текстовый файл, а затем открою его с явно установленной кодировкой «utf-8», строка появится правильно, и os.path.exists() возвращает Истина. Что происходит не так и как это исправить?

Изменить: вот код, который я только что написал, чтобы продемонстрировать свою проблему:

from pymongo import MongoClient

db = MongoClient().test_db
orig_doc = {'string': 'E=mc²'}
_id = db.test_col.insert(orig_doc)
new_doc = db.test_col.find_one(_id)
print(new_doc['string'])

>>> E=mc²

Как видите, он работает именно так, как должен! Таким образом, теперь я понимаю, что я, должно быть, ошибся, когда мигрировал с PostgreSQL. Теперь мне просто нужно починить струны. Я знаю, что это возможно, но должен быть лучший способ, чем запись строк в текстовый файл, а затем чтение их обратно. Я мог сделать это так же, как и в предыдущем тестировании, но мне кажется, что это неправильный путь.


person Steohawk    schedule 11.11.2014    source источник
comment
Не могли бы вы включить код? Кажется, вам не хватает параметра или вызова, указывающего кодировку. Кажется, на самом деле ничего не происходит, вы только возвращаете данные в неправильной кодировке.   -  person Simeon Visser    schedule 12.11.2014


Ответы (1)


Вы не можете хранить Unicode. Это концепция. MongoDB должен использовать кодировку Unicode, и она выглядит как UTF-8. Строки Unicode Python 3 хранятся внутри как одна из нескольких кодировок в зависимости от содержимого строки. У вас есть строка, декодированная в Unicode с неправильной кодировкой:

>>> s='"C:\Some Folder\E=mc².xyz"'  # The invalid decoding.
>>> print(s)
"C:\Some Folder\E=mc².xyz"
>>> print(s.encode('latin1').decode('utf8'))  # Undo the wrong decoding, and apply the right one.
"C:\Some Folder\E=mc².xyz"

Недостаточно информации, чтобы рассказать вам, как правильно читать MondoDB, но это должно вам помочь.

person Mark Tolonen    schedule 12.11.2014
comment
Ваш ответ пришел как раз перед тем, как я закончил редактировать свой пост. Я только что проверил ваше решение, и оно работает! Огромное спасибо! - person Steohawk; 12.11.2014