[Tutor] Appropriate use of None

Mats Wichmann mats at wichmann.us
Sat Jan 1 12:43:46 EST 2022


On 1/1/22 04:48, Manprit Singh wrote:
> Dear Sir,
> 
> Consider an example of reading a file, along with exception handling in the
> below given way:
> 
> file = None
> try:
>     file =open("filefortest.txt")
>     text = file.read()
> except IOError:
>     print("File can't be read")
> else:
>     print(text)
> finally:
>     if file != None:
>         file.close()
>         print("File is closed")
> 
> Here I have assigned None to a variable file in the beginning. Then in try
> block
> the file object is assigned to the same variable file. This is done so to
> make the variable "file" available in finally block holding a value "None"
> when an exception
> is raised in the try block while reading the file.
> 
> Kindly comment if this kind of practice should be done or not ?

Alan has already replied well so I know I'm just piling on here.

You're trying to handle two situations with this piece of code:

1. opening/reading a file, which might throw an error
2. making sure the file resource is cleaned up when you're done with it.

For the latter, using a context manager is helpful because it shortens
the "boilerplate" we otherwise have to write, which consists of:

setup resource that needs cleanup
try:
    work with resource
finally:
    cleanup

and now can become

with resource that needs cleanup
    work with resource

as long as a context manager has been defined for that resource - this
would be a class that provides two special methods, __enter__ and
__exit__, which are the "setup" and "cleanup" steps from the original.
And such a context manager has indeed been provided in the standard
Python language for file opening, so you can use the "with" statement
happily here - and not need to use a sentinel.

you still want a try block to handle possible errors opening the file,
if you're being careful.

Meanwhile, your None question:  use of an out-of-band value as a
sentinel to enable you to detect that some piece of code did not
actually execute is in general fine, as long as you commit to actually
doing that test - which you are doing, so that's good.  In your piece of
code it's pretty obvious, but many times it isn't - someone writes a
function which returns some type of data, but can also return None if
the data could not be determined. Then callers just go ahead and act on
the returned data, not checking (maybe not knowing that they needed to,
if documentation is incomplete or whatever reason) for None first. And
then you get the dreaded error:

AttributeError: 'NoneType' object has no attribute 'close'

There was a recent article on this topic that you (and others?) might
find interesting - I'll stop writing now and let this guy go into many
more details....

https://engineeringblog.ridereport.com/pythons-none-problem



More information about the Tutor mailing list