Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #196383 > unrolled thread

Re: Best use of "open" context manager

Started byThomas Passin <list1@tompassin.net>
First post2024-07-06 09:40 -0400
Last post2024-07-06 09:40 -0400
Articles 1 — 1 participant

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Best use of "open" context manager Thomas Passin <list1@tompassin.net> - 2024-07-06 09:40 -0400

#196383 — Re: Best use of "open" context manager

FromThomas Passin <list1@tompassin.net>
Date2024-07-06 09:40 -0400
SubjectRe: Best use of "open" context manager
Message-ID<mailman.7.1720273834.2981.python-list@python.org>
On 7/6/2024 6:49 AM, Rob Cliffe via Python-list wrote:
> Consider this scenario (which I ran into in real life):
>      I want to open a text file and do a lot of processing on the lines 
> of that file.
>      If the file does not exist I want to take appropriate action, e.g. 
> print an error message and abort the program.
> I might write it like this:
> 
> try:
>      with open(FileName) as f:
>          for ln in f:
>              print("I do a lot of processing here")
>              # Many lines of code here .....
> except FileNotFoundError:
>      print(f"File {FileName} not found")
>      sys.exit()
> 
> but this violates the principle that a "try" suite should be kept small, 
> so that only targeted exceptions are trapped,
> not to mention that having "try" and "except" far apart decreases 
> readability.
> 
> Or I might write it like this:
> 
> try:
>      f = open(FileName) as f:
>      FileLines = f.readlines()
> except FileNotFoundError:
>      print(f"File {FileName} not found")
>      sys.exit()
> # I forgot to put "f.close()" here -:)
> for ln in File Lines:
>          print("I do a lot of processing here")
>          # Many lines of code here .....
> 
> but this loses the benefits of using "open" as a context manager,
> and would also be unacceptable if the file was too large to read into 
> memory.
> 
> Really I would like to write something like
> 
> try:
>      with open(FileName) as f:
> except FileNotFoundError:
>      print(f"File {FileName} not found")
>      sys.exit()
> else: # or "finally:"
>          for ln in f:
>              print("I do a lot of processing here")
>              # Many lines of code here .....
> 
> but this of course does not work because by the time we get to "for ln 
> in f:" the file has been closed so we get
> ValueError: I/O operation on closed file
> 
> I could modify the last attempt to open the file twice, which would 
> work, but seems like a kludge (subject to race condition, inefficient).
> 
> Is there a better / more Pythonic solution?

I usually read the file into a sequence of lines and then leave the 
open() as soon as possible.  Something like this:

FILENAME = 'this_is_an_example.txt'
lines = None
if os.path.exists(FILENAME):
     with open(FILENAME) as f:
         lines = f.readlines()
# do something with lines

Of course, if you want to read a huge number of lines you will need to 
be more thoughtful about it.  Or make all the processing within the 
open() block be a function.  Then you just have one more line in the block.

[toc] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web