"Pythonic" way to handle maybe-empty query responses? #552
-
|
This isn't necessarily an apsw-specific question, if anything it's more of a thinking-aloud ramble. Hopefully it's not too annoying. I often find myself writing queries that look like this: foo, bar = db.execute("SELECT foo, bar FROM mytable WHERE baz=?", (baz,)).fetchone()On the happy path, I expect 1 row to be returned. But there might be 0 rows returned - fetchone() will return None, and python will raise So then I might write something like this: try:
foo, bar = db.execute("SELECT foo, bar FROM mytable WHERE baz=?", (baz,)).fetchone()
except TypeError:
print("oh no")or maybe row = db.execute("SELECT foo, bar FROM mytable WHERE baz=?", (baz,)).fetchone()
if row is None:
raise Exception("oh no")
foo, bar = rowBoth of these feel a little janky to me, for different reasons. The first one is non-obvious what's going on without a comment to explain (and there are other potential TypeError causes, too), and the second is more explicit but means littering my code with temporary "row" variables. So my general question is, is there a more graceful and "pythonic" way of doing this that I haven't thought of? I'm curious what other people are doing because I'm sure this general pattern is common. Maybe I could write a wrapper function like so: def exec_one(db, query, params) -> tuple:
cur = db.execute(query, params)
row = cur.fetchone()
if row is None:
raise MyEmptyResponseException("0 rows returned")
if cur.fetchone() is not None:
raise Exception("Expected a single row, but there were more")
return row(the final check is perhaps unnecessary) |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 1 reply
-
|
I wonder, is there some way I could subclass |
Beta Was this translation helpful? Give feedback.
-
|
Here's my latest thought, a generic "make sure it's not None" helper class NoneError(TypeError):
pass
T = TypeVar("T")
def definitely(obj: Optional[T]) -> T:
if obj is None:
raise NoneError("Expected something, but found None")
return objWhich I can use like so: try:
foo, bar = definitely(db.execute("SELECT foo, bar FROM mytable WHERE baz=?", (baz,)).fetchone())
except NoneError:
print("oh no") |
Beta Was this translation helpful? Give feedback.
-
|
Have you considered using get? It will return This will set |
Beta Was this translation helpful? Give feedback.
-
|
You may also be able to do some shenanigans with apsw.pyobject. For example this makes a function that will create a tuple: So your query can either return a result of N values or I have always wanted some way of fixing queries at a higher level so you don't repeat yourself so that this couldn't have errors: It is irritating to have to repeat the names at the Python level and at the SQL level and ensure they match. |
Beta Was this translation helpful? Give feedback.
-
|
You can also use That outputs: Since match statements don't have to be exhaustive you don't have to include the I suspect |
Beta Was this translation helpful? Give feedback.
You can also use
matchstatements withget:That outputs:
Since match statements don't h…