3

I often see this in code:

with open(file_path) as f:
    json_content = json.load(f)

And less often this:

json_content = json.load(open(file_path))

I was wondering if the latter is an anti pattern or what the difference between the two versions is.

Dominik Neise
  • 1,179
  • 1
  • 10
  • 23
  • The latter relies on the GC to close the file. That's not a good idea. If someone doesn't use CPython the GC might not be using refcounting but e.g. collect garbage only after some time which would keep the file open until then. – ThiefMaster Sep 12 '16 at 09:47
  • 1
    @ThiefMaster I think your comment basically nails it. None of the other answers points out the fact, that the latter version basically relies on CPythons GC implementation. If you move your comment into an anwer, I would like to accept it. – Dominik Neise Sep 12 '16 at 10:49
  • posted it as an answer – ThiefMaster Sep 12 '16 at 11:45

3 Answers3

1

When you use a context manager, it guarantees that your file will be close automatically at the end of block. The with statement does this by calling the close attribute of the file object, using its __exit__() method.

As said in document:

The with statement guarantees that if the __enter__() method returns without an error, then __exit__() will always be called.

Read about more features https://docs.python.org/3.5/reference/compound_stmts.html#with

Mazdak
  • 105,000
  • 18
  • 159
  • 188
1

json.load(open(file_path)) relies on the GC to close the file. That's not a good idea: If someone doesn't use CPython the garbage collector might not be using refcounting (which collects unreferenced objects immediately) but e.g. collect garbage only after some time.

Since file handles are closed when the associated object is garbage collected or closed explicitly (.close() or .__exit__() from a context manager) the file will remain open until the GC kicks in.

Using with ensures the file is closed as soon as the block is left - even if an exception happens inside that block, so it should always be preferred for any real application.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
0

In addition to other answers, a context manager is very similar to the try-finally clause.

This code:

with open(file_path) as f:
    json_content = json.load(f)

can be written as:

f = open(file_path)
try:
    json_content = json.load(f)
finally:
    f.close()

The former is clearly preferable.

VPfB
  • 14,927
  • 6
  • 41
  • 75