The latter uses a Python context manager to open the file, the former doesn't. By using the open() context manager like this, you don't need to worry about closing the file yourself, since the context manager takes care of it. The code that runs inside the 'with' block gets yielded inside the context manager. The former version of the code does not store a reference to the file handle, thus cannot close the file handle. Of course you can close file handles without using a context manager too:
It's documented in PyPy differences, but generally open('x').read() does not guarantee that a file is closed. In CPython it's not a problem due to refcounting, but in pypy, the file might be closed at some later stage. There is additionally a silly low number of open file descriptors, which limits how many files you can have open at once.
> In CPython it's not a problem due to refcounting, but in pypy, the file might be closed at some later stage.
Technically the guarantee in CPython is "soft" so it can be a problem, just rarely is: if the file gets referenced from an object accessible from a cycle the file won't be released (and closed) until the cycle-breaking GC is triggered.
contents = open(file).read()
where they should be doing
with open(file) as fid: contents = fid.read()