Stop writing Python 3.5 incompatible code :-)

Chris Angelico rosuav at gmail.com
Thu Jan 14 03:07:59 EST 2016


On Thu, Jan 14, 2016 at 6:36 PM, Frank Millman <frank at chagford.com> wrote:
> I like your first solution. In fact, with sqlite3, 'cur' is already
> iterable, so I can just say
>
> cur.execute(...)
> try:
>    row = next(cur)
> except StopIteration:
>    # 0 rows returned
> try:
>    next(cur)
> except StopIteration: pass
> else:
>    # >1 rows returned
>
> I will have to check if this works with psycopg2 and pyodbc, the other two
> adaptors that I use.

Not sure that "already iterable" means what you think it does. Since
it's iterable, you can call iter() on it (as I do in my example).

> Your second solution does not seem to work - if it raises StopIteration,
> neither 'row' nor 'extra' is populated. I may be doing it wrong, but no
> matter, I prefer the first one anyway.

Oops.

cur.execute(...)
rows = iter(cur)
row, extra = next(rows, None), next(rows, None)
if row is None:
    # 0 rows returned
if extra is not None:
    # >1 rows returned

Now it's set.

> There is one slight downside that I can see. I believe that raising an
> exception is a relatively expensive operation in Python. For this reason, a
> rule of thumb is to use EAFP when the usual case is to have no exception,
> and LBYL otherwise. With my approach, I do not get an exception if exactly
> one row is returned. With yours, you rely on raising an exception to
> determine the result.

Under the hood, they're all doing the same thing.

> I can think of two counter-arguments to that. Firstly, it is more important
> to ensure that the program is correct than to shave off a few microseconds.
> Secondly, as StopIteration is used extensively under the hood in modern
> pythons, it is probably highly optimised, and therefore nothing to be
> worried about.

Thirdly, the cost of raising an exception is WAY lower than the cost
of reading anything from a hard disk - probably way lower than reading
from an SSD. Unless all your content is getting cached in RAM, there's
no way the cost of an exception will be at all significant.

ChrisA



More information about the Python-list mailing list