2012-05-15 25 views
5

Tôi đang sử dụng mongodb và redis, redis là bộ nhớ cache của tôi.Lưu unicode trong redis nhưng lấy lỗi

Tôi nhớ đệm đối tượng MongoDB với redis-py:

obj in mongodb: {u'name': u'match', u'section_title': u'\u6d3b\u52a8', u'title': 
u'\u6bd4\u8d5b', u'section_id': 1, u'_id': ObjectId('4fb1ed859b10ed2041000001'), u'id': 1} 

các obj lấy từ redis với hgetall (key, obj) là:

{'name': 'match', 'title': '\xe6\xaf\x94\xe8\xb5\x9b', 'section_title': 
'\xe6\xb4\xbb\xe5\x8a\xa8', 'section_id': '1', '_id': '4fb1ed859b10ed2041000001', 'id': '1'} 

Như bạn thấy, obj vời từ bộ nhớ cache là str thay vì unicode, vì vậy trong ứng dụng của tôi, có lỗi giống như: 'ascii' codec không thể giải mã byte 0xe6 ở vị trí 12: thứ tự không nằm trong phạm vi (128)

Có thể đưa ra một số đề xuất không? cảm ơn u

+1

Và cách bạn lưu các đối tượng mongodb bằng redis? – Denis

Trả lời

7

Cập nhật, để cài đặt chung, hãy kiểm tra jmoz's answer.

Nếu bạn đang sử dụng của bên thứ ba lib như django-redis, bạn có thể cần phải xác định một tùy chỉnh ConnectionFactory:

class DecodeConnectionFactory(redis_cache.pool.ConnectionFactory): 
    def get_connection(self, params): 
     params['decode_responses'] = True 
     return super(DecodeConnectionFactory, self).get_connection(self, params) 

Giả sử bạn đang sử dụng redis-py, bạn muốn tốt hơn để vượt qua str thay vì unicode thành Redis hoặc nếu không Redis will encode it automatically cho các lệnh *set, thường là in UTF-8. Đối với các lệnh *get, Redis không có ý tưởng về loại giá trị chính thức và phải trả lại trực tiếp giá trị trong số str.

Vì vậy, theo Denis, cách bạn lưu trữ đối tượng vào Redis là rất quan trọng. Bạn cần chuyển đổi giá trị thành str để làm cho lớp Redis trong suốt cho bạn.

Ngoài ra, set the default encoding to UTF-8 thay vì sử dụng ascii

+0

Tại sao họ sẽ tự động mã hóa nó nhưng sau đó chỉ để lại cho bạn một chuỗi trên có được? – jmoz

+0

@jmoz Tôi không chắc chắn, có thể tác giả biết lý do = p.Nhưng không giống như bộ điều hợp như psycopg2, thông thường máy khách redis-py không lưu trữ dữ liệu ban đầu với dữ liệu. Do đó không có cách nào để biết chính xác loại dữ liệu (chuỗi) nào là ban đầu và cách giải mã nó. Có thể nhấn mạnh vào 'str' thay vì chấp nhận các loại giá trị khác sau đó chuyển đổi chúng thành' str' ngầm, là tốt hơn, nhưng ai biết được. – okm

+1

@okm Tôi tìm thấy một cái gì đó vào ngày khác liên quan đến điều này, kiểm tra câu trả lời của tôi. – jmoz

6

cho mỗi chuỗi, bạn có thể sử dụng hàm decode để chuyển đổi nó thành utf-8, ví dụ: cho giá trị nếu trường tiêu đề trong mã của bạn:

In [7]: a='\xe6\xaf\x94\xe8\xb5\x9b' 

In [8]: a.decode('utf8') 
Out[8]: u'\u6bd4\u8d5b' 
+0

Người đàn ông tôi nghĩ rằng hi là muốn làm cho bộ nhớ cache không cho giải mã mã hóa vui vẻ, nhưng để tăng hệ thống. – Denis

3

Tôi đề nghị bạn luôn mã hóa thành utf-8 trước khi viết cho MongoDB hoặc Redis (hoặc bất kỳ hệ thống bên ngoài nào). Và bạn giải mã ('utf-8') khi bạn kết quả fecth, để bạn luôn làm việc với Unicode trong Python.

25

Tôi nghĩ rằng tôi đã phát hiện ra vấn đề. Sau khi đọc điều này, tôi phải giải mã một cách rõ ràng từ redis, đó là một nỗi đau, nhưng hoạt động.

Tôi tình cờ gặp một bài đăng trên blog nơi kết quả của tác giả là tất cả các chuỗi unicode mà obv khác với tôi.

Nhìn vào StrictRedis.__init__ có thông số decode_responses theo mặc định là False. https://github.com/andymccurdy/redis-py/blob/273a47e299a499ed0053b8b90966dc2124504983/redis/client.py#L446

Vượt qua decode_responses=True để xây dựng và cho tôi CỐ ĐỊNH CỦA LUẬT này.

+0

Cảm ơn bạn, tôi sẽ thử sau. Đây có lẽ là giải pháp tốt nhất vì tôi sẽ không làm hỏng mã của tôi. – goofansu

+0

Điều này thật tuyệt vời. Cảm ơn. –

+1

Đây phải là câu trả lời được chấp nhận – raben

Các vấn đề liên quan