0

I generally like to use the with open(...) as file: idiom for opening files because it avoids failing to close a file, improves code readability, and improves exception handling. However, I have seen other people's code use one-liners to open and read/write a file without saving the TextIOWrapper object:

# Read a file
contents = open('the_file.txt').read()

# Write to a file
open('the_file.txt', 'w').write('This is the thing.')

# Write an empty file
open('empty_file.txt', 'w')

These idioms are appealing because of their simplicity, but I want to understand what python does with those file objects.

I tried using the dis module to inspect the bytecode, but I'm not sure how to read the output:

def myfunc():
    open('test.txt', 'w')
dis.dis(myfunc)
  2           0 LOAD_GLOBAL              0 (open)
              2 LOAD_CONST               1 ('test.txt')
              4 LOAD_CONST               2 ('w')
              6 CALL_FUNCTION            2
              8 POP_TOP
             10 LOAD_CONST               0 (None)
             12 RETURN_VALUE
def withfunc():
    with open('test.txt', 'w') as f:
        pass
dis.dis(withfunc)
  2           0 LOAD_GLOBAL              0 (open)
              2 LOAD_CONST               1 ('test.txt')
              4 LOAD_CONST               2 ('w')
              6 CALL_FUNCTION            2
              8 SETUP_WITH               6 (to 16)
             10 STORE_FAST               0 (f)

  3          12 POP_BLOCK
             14 LOAD_CONST               0 (None)
        >>   16 WITH_CLEANUP_START
             18 WITH_CLEANUP_FINISH
             20 END_FINALLY
             22 LOAD_CONST               0 (None)
             24 RETURN_VALUE
def savefunc():
    f = open('test.txt', 'w')
    f.close()
dis.dis(savefunc)
  2           0 LOAD_GLOBAL              0 (open)
              2 LOAD_CONST               1 ('test.txt')
              4 LOAD_CONST               2 ('w')
              6 CALL_FUNCTION            2
              8 STORE_FAST               0 (f)

  3          10 LOAD_FAST                0 (f)
             12 LOAD_ATTR                1 (close)
             14 CALL_FUNCTION            0
             16 POP_TOP
             18 LOAD_CONST               0 (None)
             20 RETURN_VALUE

I have two questions:

  1. What happens under the hood when you use open without saving the TextIOWrapper object (especially regarding whether they are properly closed)
  2. Are there reasons to NOT use the one-liners?
reynoldsnlp
  • 1,072
  • 1
  • 18
  • 45
  • `dis` isn't going to really help you here, you have to know the implementations of the objects themselves – juanpa.arrivillaga Nov 20 '18 at 21:07
  • Never `open()` without referencing the obj. The object remains in memory and cannot be freed since you don't reference to `close()` with. – r.ook Nov 20 '18 at 21:10
  • 1
    @Idlehands that's not true. it will be freed (in CPython), and closed, but the output buffer won't necessarily write to disk. Well, actually, that only happens if you *do* have a reference around, because CPython doesn't guarantee that `__del__` will be called for objects that still have references when the interpreter shuts down. – juanpa.arrivillaga Nov 20 '18 at 21:11
  • You should always just use a context-manager. – juanpa.arrivillaga Nov 20 '18 at 21:14

0 Answers0