Interactive mode within "with" statements

Viewed 146

With statement context managers are convenient for many purposes. However, they can be inconvenient in an interactive shell, because the entire with statement is executed as a whole block, e.g.:

with open('test.txt', 'r') as fin:
    print(fin.readline())  # The result does not immediately output to the console
    for i in range(10):  # I may want to choose the number depending on the previous line's output
                         # (or do something else entirely), but I cannot
        print(fin.readline())  # Or any other sort of processing

As shown, this may be a problem if, for example, I want to "explore" a file's content before deciding what to do with it. What I usually end up doing is either reading the entire file into a string before processing it, or use multiple with statements to open the file multiple times, but obviously both of those solutions have limitations (e.g. the file may be too large to read into the memory, or the context manager in question may not be a file at all).

A more general solution would be to eschew the with statement and use fin.close() instead. However, some context manager classes I use may not provide a close() method in their public interface. Of course I could explicitly write mycontextmanager.__exit__(None, None, None), but that seems awkward. Also, it is also entirely possible that I'd forget to close the context manager, which is not a big deal for files, but may be more problematic for e.g. an internet session.

I could also use finalizers to make sure that things are closed, but relying on the garbage collector for anything other than memory leaks seems a shaky way to do things, so I feel that finalizers should be a supplemental solution at best.

So is there a more elegant solution to the problem of using context managers in an interactive shell? Should my own context manager classes always provide something like a close() method as a good practice?

1 Answers

Run an interactive session through the debugger.

Run the code as a script but put a breakpoint() in a point of interest.

See here for the debugger docs.

  • s to step
  • n (next) to step over functions
  • c (continue) to resume execution
  • p <name> to display names's value
  • ! <statement> to execute a statement
  • display <name> is useful too.
Related