0

The cache would have an initial size of 20 elements and upon reaching its limit, to add any new element it would remove the least recently accessed element. On shutdown it should store the cached data back to the file. The data should be stored in the cache according to a caching strategy. Provide options for cache CRUD. Testing Data set : records of student.

import json
from collections import OrderedDict
import time
import os

if os.path.exists("qwerty.json"):
    record = json.load(open("qwerty.json", "r"), object_pairs_hook=OrderedDict)
else:
    record = OrderedDict({})

fo = open("foo.txt", "wb")

x = list(record.items())[:20]; x2 = sorted(x, key=lambda k: k[1]['time'], reverse=True)
print(x2)

command = ""
while command != 'exit':
    command = input('Enter a command(options: create,read,save): ')
    if command == "create":
        name = input('Enter name of the Student:')
        p = input('Student ID: ')
        a = input('Class: ')
        n = input('Marks: ')
        time = time.time()

        record[name] = {'Student ID:': p, 'Class:': a, 'Marks': n, 'time': time }

    elif command == 'read':
        z = json.load(open("qwerty.json", "r"), object_pairs_hook=OrderedDict)
        print(z)

    elif command == 'save':
        json.dump(record, open('qwerty.json', "w"))

fo.close()
  • ...So what's your question? – cs95 Jul 02 '17 at 21:02
  • I am currently performing: Create , Read , Save only but on that load of my json file i have to implement a cache (i.e. a another file ) that would contain of 20 elements and upon reaching its limit, to add any new element it would remove the least recently accessed element. I am not getting the part to how to do same in python. Please help... – Ayush Asthana Jul 02 '17 at 21:08
  • Okay, I think I got it. – cs95 Jul 02 '17 at 21:11
  • Please help if you can...pls – Ayush Asthana Jul 02 '17 at 21:14

1 Answers1

1

You can actually maintain order with a single file, using a combination of json and collections.OrderedDict.

Your initial setup is like so:

from collections import OrderedDict
phone_book = OrderedDict({})

When creating, add elements into an ordered dict and then dump it as JSON. The order of keys is preserved. After you declared phone_book like above, the rest of the code for create remains the same. Note that when you write to the file, you don't close it, so you can't read the contents later. This should be replaced with something like:

import os

if os.path.exists("qwerty.json")
    phone_book = json.load(open("qwerty.json", "r"), object_pairs_hook=OrderedDict)
else:
    phone_book = OrderedDict({})

command = ""
while command != 'exit':
    command = input('Enter a command(options: create,read,save): ')
    if command == "create":
        ...

    elif command == 'read':
        ...

    elif command == 'save':
        json.dump(phone_book, open('qwerty.json', "w"))

For reading, you'll have to make some changes:

elif command == 'read':
    z = json.load(open("C:\\Users\\qwerty.txt", "r"), object_pairs_hook=OrderedDict)
    ...

This loads the dict in the order the keys were stored. You can now call list(z.items())[-20:] to get only the last 20 items. Also, when reading a particular key, you update its "last-read-time" by deleting and recreating it:

import copy
key = ...
temp = copy.copy(z[key])
del z[key]
z[key] = temp

This will update the position of key in the dict. This should be enough for you to implement the rest yourself.

cs95
  • 379,657
  • 97
  • 704
  • 746
  • but through 'OrderedDict'....I am not able to read the Dict. as I am getting this error:File "C:\Python\Python35\lib\json\__init__.py", line 268, in load parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw) File "C:\Python\Python35\lib\json\decoder.py", line 357, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) – Ayush Asthana Jul 02 '17 at 21:37
  • @AyushAsthana You no longer need `z.read()`. That's for reading from a file pointer. Remove that line. You're having the `json` module directly read the file and pass you the data. – cs95 Jul 02 '17 at 21:37
  • that I have already removed...by mistake i mentioned here...but still I am getting the same error: json.decoder.JSONDecodeError: – Ayush Asthana Jul 02 '17 at 21:39
  • @AyushAsthana Update the question with your latest code. – cs95 Jul 02 '17 at 21:40
  • @AyushAsthana Change `f.write(json.dumps(phone_book))` -> `json.dump(phone_book, f)` – cs95 Jul 02 '17 at 21:49
  • Now on save: TypeError: <_io.TextIOWrapper name='C:\\Users\\AYUSH ASTHANA\\Desktop\\qwerty.txt' mode='w' encoding='cp1252'> is not JSON serializable & on READ : JSONDecodeError: Expecting value: line 1 column 1 (char 0) – Ayush Asthana Jul 02 '17 at 21:51
  • @AyushAsthana It's `json.dump(phone_book, f)`. My bad :) – cs95 Jul 02 '17 at 21:52
  • @AyushAsthana Your problem is that you keep the file open. The data is not written till the file is actually closed: Look at this (I fixed your code): https://pastebin.com/S6VBBHuE – cs95 Jul 02 '17 at 22:00
  • Thanks...for pointing it out...actually I'm new to python and I'm stuck on this from hours...can you please help me for transferring the 20 element to another file(cache) updating same by eliminating the least recent used through time-stamp I'm using... – Ayush Asthana Jul 02 '17 at 22:26
  • @AyushAsthana I already gave you an idea of how to do it... now it's your turn. If you are spoonfed, you will never learn. :) If this question helped, please consider marking it accepted. Much appreciated. – cs95 Jul 02 '17 at 22:28
  • @AyushAsthana Cheers. All the best. Do your best on your own. If you still get stuck, then as a last resort ask a new question and keep it specific. :) – cs95 Jul 02 '17 at 22:44
  • Just tell me one last thing....I want to sort my list element by timestamp...in the present above code..pls have a look – Ayush Asthana Jul 03 '17 at 09:05
  • sorry ..my bad....I want to print the [:20] elements sorted by time stamp....print ("%s%s" % (k, record[k])); – Ayush Asthana Jul 03 '17 at 09:13
  • `x = list(z.items())[-20:]; x2 = sorted(x, key=lambda k: k[1]['time'], reverse=True)` – cs95 Jul 03 '17 at 09:15
  • It doesn't sort by timestamp – Ayush Asthana Jul 03 '17 at 09:37
  • @AyushAsthana Just modify the key... It is sorting lexicographically now. – cs95 Jul 03 '17 at 09:42
  • This should help: https://stackoverflow.com/questions/2803852/python-date-string-to-date-object – cs95 Jul 03 '17 at 09:42
  • Or better still... when you create the record, don't save it in iso format. Save it in Epochs (integer, therefore easy to sort). – cs95 Jul 03 '17 at 09:43
  • eyah..that is the problem....besides ISO format....it throws error for 'not JSON serializable' – Ayush Asthana Jul 03 '17 at 09:50
  • @AyushAsthana You can do `import time; my_date = time.time()` returning the time as an integer. – cs95 Jul 03 '17 at 09:51
  • this gives me..{"Student ID:": "123", "Class:": "12", "Marks": "123", "time": 1499076408.3859165} – Ayush Asthana Jul 03 '17 at 10:08
  • @AyushAsthana You can easily convert it to string format later using date time library... google it... :) – cs95 Jul 03 '17 at 10:09
  • ok...but still I am not able to sort it on above code...and on this data...https://pastebin.com/kzhDL0y5 – Ayush Asthana Jul 03 '17 at 10:24
  • @AyushAsthana Just ask a new question. :) This thread is becoming too long. – cs95 Jul 03 '17 at 10:25
  • You've asked 2 questions recently, some of which have not been received very well by the community. Everyone learns at their own pace, and it’s okay to make some mistakes. However, the reception your questions have received thus far might ultimately block your account from asking questions entirely. – Ayush Asthana Jul 03 '17 at 10:27
  • Oh... Did you try `x2 = sorted(x, key=lambda k: k[1]['time'], reverse=True)` Why isn't it working? – cs95 Jul 03 '17 at 10:29
  • I have tried..but sorting ain't happening...you can see same in above code...if something is wrong... – Ayush Asthana Jul 03 '17 at 10:34
  • @AyushAsthana `x = list(record.items())[-20:];` – cs95 Jul 03 '17 at 10:36
  • ok thanks...can you tell me why my dictionary key,value order gets change...every other time I create... for e.g. "A0003": {"time": 1499078603.4269066, "Class:": "12", "Student ID:": "123", "Marks": "120"}, & "j133": {"Student ID:": "221", "Class:": "12", "Marks": "462", "time": 1499089539.5566998}, IS IT DUE TO OrderedDict..? – Ayush Asthana Jul 03 '17 at 10:49
  • Dictionaries do not have an implicit ordering for versions of python below 3.6. You can use an OrderedDict for the inner dicts as well, if you wish. – cs95 Jul 03 '17 at 10:59
  • so if the order is getting changed every time...on every 'create'....k[1]['time'] will be of no use...because it's position gets changed everytime....right..? – Ayush Asthana Jul 03 '17 at 11:20
  • Yeah. Only the positions of the inner dict. – cs95 Jul 03 '17 at 11:20
  • so...is there any solution for same...by which I can take the 'time' value and then sort it..? – Ayush Asthana Jul 03 '17 at 11:22