11

I have written a small web application, and with each request I should open and read a JSON file. I am using pickledb for this purpose. What concerns me about it, is that the library passes open() as a parameter for the json.load() function . So it got me thinking ..

When I write code like this:

with open("filename.json", "rb") as json_data:
    my_data = json.load(json_data)

or

json_data = open("filename.json", "rb")
my_data = json.load(json_data)
json_data.close()

I am pretty sure that the file handle is being closed.

But when I open it this way :

my_data = json.load(open("filename.json", "rb"))

The docs say that json.load() is expecting a .read()-supporting file-like object containing a JSON document.

So the question is, will this handle stay open and eat more memory with each request? Who is responsible for closing the handle in that case?

Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55
Alexander
  • 12,424
  • 5
  • 59
  • 76
  • My feeling is that the file will be opened as long as a reference exists the the `open(...)`-returned object, which means as long as the `json.load(...)` function has not returned. But I've got no documentation to support this. – Joël Mar 12 '14 at 11:21
  • Check out why `with open(...) as f` should be used. I'm sure it contains an explanation that says why and that it also mentions when the file would be closed otherwise. BTW: The second method you mention is unsafe, too, and exactly that should be explained there, too. – Ulrich Eckhardt Feb 27 '18 at 08:59

2 Answers2

2

Close method of the file will be called when object is destroyed, as json.load expects only read method on input object.

What happens depends on garbage collection implementation then. You can read more in Is explicitly closing files important?

Generally speaking it's a good practice to take care of closing the file.

Community
  • 1
  • 1
Slawek Rewaj
  • 809
  • 8
  • 16
2

I tried to somehow fake file-like object with read() and close() methods, and stick it into json.load(). Then I observed, that close() is not being called upon leaving context. Hence, I would recommend to close the file object explicitly. Anyway, doc says that the loading method expects read() method, but does not say it expects close() method on the object.

In test.json:

{ "test":0 }

In test.py:

import json

class myf:
    def __init__(self):
        self.f = None

    @staticmethod
    def open(path, mode):
        obj = myf()
        obj.f = open(path, mode)
        return obj

    def read(self):
        print ("READING")
        return self.f.read()

    def close(self):
        print ("CLOSING")
        return self.f.close()

def mytest():
    s = json.load(myf.open("test.json","r"))
    print (s)

mytest()
print("DONE")

Output:

$> python test.py
READING
{u'test': 0}
DONE
$>
lef
  • 1,196
  • 1
  • 9
  • 18