You can rely on a GC (and refcounting + a cycle collector is absolutely a GC) to finalize your resources for you, but it is quite difficult to reason about when the file will eventually be closed.
Also, the reference counting semantics of CPython are implementation-specific. From the PEP that introduced `with`:
> Note that we're not guaranteeing that the finally-clause is executed immediately after the generator object becomes unused, even though this is how it will work in CPython. This is similar to auto-closing files: while a reference-counting implementation like CPython deallocates an object as soon as the last reference to it goes away, implementations that use other GC algorithms do not make the same guarantee. This applies to Jython, IronPython, and probably to Python running on Parrot.