How Best to Coerce Python Objects to Integers?

Steve D'Aprano steve+python at pearwood.info
Tue Jan 3 19:26:08 EST 2017


On Wed, 4 Jan 2017 10:09 am, Ethan Furman wrote:

> And, of course, whether or not "except Exception" is too broad depends on
> the use-case.

I'm having trouble thinking of *any* use-case where this would be useful.
His intention, it seems, is to write a function which simply cannot fail,
presumably so that he can write code which consumes the output and just
keeps going no matter what he throws at it:

graph = make_graph()
incoming_data = [1, 12, 7, "hello", None, [], {}, 5]
for obj in incoming_data:
    graph.draw_point(int_or_else(obj))


But of course that's impossible:

class Evil:
    def __int__(self):
        os.abort()

Or for that matter:

class Evil:
    def __int__(self):
        time.sleep(2147483647)



So his code still can fail under some circumstances. And so it should. Why
is my input data including such evil objects? I should find out why. I'm
having trouble seeing how it could be anything but a programming bug.


He gives the rationale for this function:

    A scenario that’s more realistic than the Unintable class might
    be a class that wraps an industrial sensor. Calling int() on an
    instance normally returns a value representing pressure or
    temperature. However, it might reasonably raise a
    SensorNotReadyError.

Okay. Let's suppose it can return either an integer as a string, some
arbitrary non-numeric string to indicate a sensor error, or raises
SensorNotReadyError. Then this would be an appropriate function to use:

def int_or_else(value):
    try:
        return int(value)
    except ValueError:
        assert isinstance(value, str)
        # consider logging the error?
        return None
    except SensorNotReadyError:
        return None


Now when he connects up to the sensor and starts reading values, it will
work, but if his input gets contaminated with arbitrary junk objects (a
sign of a programming bug in his code) he will find out about it.


One possible use-case might be something like Excel, where there are two
data types: numbers, and text, and numeric operations on text will just
skip them altogether. If you were to build an object-oriented spreadsheet,
where the cells can contain any object not just numbers and text, then you
could potentially have a situation like:

        Column A
Row 1:  1
Row 2:  ftp_server()
Row 3:  2
Row 4:  3
Row 5:  =sum(A1:A4)

and you (arguably) want the result to be 6 rather than some error. Or do
you? I can make a good case for skipping text cells, as Excel does, but I'm
not sure that ftp_server should be skipped. So I'll count that as a
use-case, but a dubious one.

Another possible use-case might be the REPL for an interpreter, where you
want the REPL to keep going no matter what exceptions take place. But I
don't think this is the right way to do that, and it's not how the Python
REPL works either.

Other than that, I'm not seeing any use-case where this sort of thing is
anything but a bad idea.





-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list