# I have the dictionary my_dict
my_dict = {
'var1' : 5
'var2' : 9
}
r = redis.StrictRedis()
Jak przechowywać my_dict i odzyskać go za pomocą redis. Na przykład poniższy kod nie działa.
#Code that doesn't work
r.set('this_dict', my_dict) # to store my_dict in this_dict
r.get('this_dict') # to retrieve my_dict
json.dumps()
zapisu jako łańcuch i po odzyskaniu od użytkownika redis wjson.loads()
celu deserializacji z powrotem do struktury danych Pythonajson.dumps()
ijson.loads()
będzie działać tylko wtedy, gdy nie przeszkadza ci, że klucze słownika zawsze są łańcuchami. Jeśli nie, możesz rozważyć użycie marynaty.hmset
nie mówi tego, ale wywołuje błąd DataError, jeśli spróbujesz zapisać pusty dykt.możesz marynować swój dykt i zapisać jako ciąg.
import pickle import redis r = redis.StrictRedis('localhost') mydict = {1:2,2:3,3:4} p_mydict = pickle.dumps(mydict) r.set('mydict',p_mydict) read_dict = r.get('mydict') yourdict = pickle.loads(read_dict)
źródło
pickle.loads
powinien być używany tylko w przypadku danych w 100% zaufanychInny sposób: możesz skorzystać z
RedisWorks
biblioteki.pip install redisworks
>>> from redisworks import Root >>> root = Root() >>> root.something = {1:"a", "b": {2: 2}} # saves it as Hash type in Redis ... >>> print(root.something) # loads it from Redis {'b': {2: 2}, 1: 'a'} >>> root.something['b'][2] 2
Konwertuje typy Pythona na typy Redis i odwrotnie.
>>> root.sides = [10, [1, 2]] # saves it as list in Redis. >>> print(root.sides) # loads it from Redis [10, [1, 2]] >>> type(root.sides[1]) <class 'list'>
Zastrzeżenie: napisałem bibliotekę. Oto kod: https://github.com/seperman/redisworks
źródło
hmset
pod maską, jeśli ustawisz zmienną na dict, a więc jeśli to zrobiszroot.something = {}
, otrzymasz DataError, ponieważhmset
nie zezwala na puste słowniki. Wspominam o tym, ponieważ dokumentacja dla redis nie mówi tego.hmset
. Przyjrzę się temu. @hlongmorePonieważ podstawowa odpowiedź została już udzielona przez innych ludzi, chciałbym dodać do niej trochę.
Poniżej znajdują się polecenia programu
REDIS
służące do wykonywania podstawowych operacji naHashMap/Dictionary/Mapping
wartościach typu.Oto ich odpowiednie metody w
redis-py
bibliotece: -Wszystkie powyższe metody ustawiające tworzą mapowanie, jeśli nie istnieje. Wszystkie powyższe metody pobierające nie generują błędów / wyjątków, jeśli mapowanie / klucz w mapowaniu nie istnieje.
Example: ======= In [98]: import redis In [99]: conn = redis.Redis('localhost') In [100]: user = {"Name":"Pradeep", "Company":"SCTL", "Address":"Mumbai", "Location":"RCP"} In [101]: con.hmset("pythonDict", {"Location": "Ahmedabad"}) Out[101]: True In [102]: con.hgetall("pythonDict") Out[102]: {b'Address': b'Mumbai', b'Company': b'SCTL', b'Last Name': b'Rajpurohit', b'Location': b'Ahmedabad', b'Name': b'Mangu Singh'} In [103]: con.hmset("pythonDict", {"Location": "Ahmedabad", "Company": ["A/C Pri ...: sm", "ECW", "Musikaar"]}) Out[103]: True In [104]: con.hgetall("pythonDict") Out[104]: {b'Address': b'Mumbai', b'Company': b"['A/C Prism', 'ECW', 'Musikaar']", b'Last Name': b'Rajpurohit', b'Location': b'Ahmedabad', b'Name': b'Mangu Singh'} In [105]: con.hget("pythonDict", "Name") Out[105]: b'Mangu Singh' In [106]: con.hmget("pythonDict", "Name", "Location") Out[106]: [b'Mangu Singh', b'Ahmedabad']
Mam nadzieję, że to wyjaśnia sprawę.
źródło
Jeśli chcesz przechowywać dyktando Pythona w redis, lepiej zapisać go jako ciąg json.
import redis r = redis.StrictRedis(host='localhost', port=6379, db=0) mydict = { 'var1' : 5, 'var2' : 9, 'var3': [1, 5, 9] } rval = json.dumps(mydict) r.set('key1', rval)
Podczas pobierania de-serializacji przy użyciu json.loads
data = r.get('key1') result = json.loads(data) arr = result['var3']
A co z typami (np. Bajty), które nie są serializowane przez funkcje json?
Można pisać funkcje kodera / dekodera dla typów, których nie można serializować za pomocą funkcji JSON. na przykład. zapisywanie funkcji kodera / dekodera base64 / ascii dla tablicy bajtów.
źródło
Można rozważyć użycie MessagePack, który jest wspierany przez redis.
import msgpack data = { 'one': 'one', 'two': 2, 'three': [1, 2, 3] } await redis.set('my-key', msgpack.packb(data)) val = await redis.get('my-key') print(msgpack.unpackb(val)) # {'one': 'one', 'two': 2, 'three': [1, 2, 3]}
Korzystanie z msgpack-python i aioredis
źródło
Inny sposób podejścia do sprawy:
import redis conn = redis.Redis('localhost') v={'class':'user','grants': 0, 'nome': 'Roberto', 'cognome': 'Brunialti'} y=str(v) print(y['nome']) #<=== this return an error as y is actually a string conn.set('test',y) z=eval(conn.get('test')) print(z['nome']) #<=== this really works!
Nie testowałem tego pod kątem wydajności / szybkości.
źródło
Polecenie redis SET przechowuje ciąg, a nie dowolne dane. Możesz spróbować użyć polecenia redis HSET, aby zapisać dict jako skrót redis z czymś w rodzaju
for k,v in my_dict.iteritems(): r.hset('my_dict', k, v)
ale typy danych redis i python nie są do siebie dopasowane. Wskazówki Pythona mogą być dowolnie zagnieżdżane, ale skrót redis będzie wymagał, aby twoja wartość była ciągiem. Innym podejściem, które możesz zastosować, jest przekonwertowanie danych Pythona na łańcuchy i przechowywanie ich w redis, na przykład
r.set('this_dict', str(my_dict))
a potem, gdy otrzymasz napis, będziesz musiał go przeanalizować, aby odtworzyć obiekt Pythona.
źródło
HMSET jest przestarzały. Możesz teraz używać HSET ze słownikiem w następujący sposób:
import redis r = redis.Redis('localhost') key = "hashexample" queue_entry = { "version":"1.2.3", "tag":"main", "status":"CREATED", "timeout":"30" } r.hset(key,None,None,queue_entry)
źródło
Wypróbuj rejson-py, który jest stosunkowo nowy od 2017 roku. Spójrz na to wprowadzenie .
from rejson import Client, Path rj = Client(host='localhost', port=6379) # Set the key `obj` to some object obj = { 'answer': 42, 'arr': [None, True, 3.14], 'truth': { 'coord': 'out there' } } rj.jsonset('obj', Path.rootPath(), obj) # Get something print 'Is there anybody... {}?'.format( rj.jsonget('obj', Path('.truth.coord')) ) # Delete something (or perhaps nothing), append something and pop it rj.jsondel('obj', Path('.arr[0]')) rj.jsonarrappend('obj', Path('.arr'), 'something') print '{} popped!'.format(rj.jsonarrpop('obj', Path('.arr'))) # Update something else rj.jsonset('obj', Path('.answer'), 2.17)
źródło
Jeśli nie wiesz dokładnie, jak uporządkować dane w Redis, zrobiłem kilka testów wydajnościowych, w tym analizę wyników. Dictonary, których użyłem ( d ), zawierało 437,084 kluczy (format md5) i wartości tej postaci:
{"path": "G:\tests\2687.3575.json", "info": {"f": "foo", "b": "bar"}, "score": 2.5}
Pierwszy test (wstawianie danych do mapowania klucz-wartość redis):
conn.hmset('my_dict', d) # 437.084 keys added in 8.98s conn.info()['used_memory_human'] # 166.94 Mb for key in d: json.loads(conn.hget('my_dict', key).decode('utf-8').replace("'", '"')) # 41.1 s import ast for key in d: ast.literal_eval(conn.hget('my_dict', key).decode('utf-8')) # 1min 3s conn.delete('my_dict') # 526 ms
Drugi test (wstawianie danych bezpośrednio do kluczy Redis):
for key in d: conn.hmset(key, d[key]) # 437.084 keys added in 1min 20s conn.info()['used_memory_human'] # 326.22 Mb for key in d: json.loads(conn.hgetall(key)[b'info'].decode('utf-8').replace("'", '"')) # 1min 11s for key in d: conn.delete(key) # 37.3s
Jak widać, w drugim teście trzeba przeanalizować tylko wartości „info”, ponieważ hgetall (klucz) już zwraca dict, ale nie zagnieżdżony.
I oczywiście najlepszym przykładem użycia Redisa jako nakazu Pythona jest pierwszy test
źródło