大量的 try 应该怎么复用

2021-07-18 08:45:16 +08:00
 plko345

一个 flask web 应用,有很多数据库操作 method,大部分 commit 是如下,想问下大家会怎么去服用


# ...

try:

    session.add(sth)

    session.commit()

except Exception as e:

    session.rollback()

    raise e

我的一些想法

  1. 函数调用,感觉不是很好

  2. 装...装饰器

  3. google 搜索到有人用 with 关键字实现,似乎还不错

  4. 在一个基类里面做一些强制措施

4586 次点击
所在节点    Python
20 条回复
MintZX
2021-07-18 09:12:59 +08:00
2 4 都行啊
ericls
2021-07-18 09:15:18 +08:00
为什么 function 不好?
learningman
2021-07-18 10:25:33 +08:00
with 最好了,自己重载一个 ContextManager
christopheredwar
2021-07-18 10:39:14 +08:00
是 sqlalchemy 麽,可以封装成一个函数,传 kwargs,往里传参数就好。
xiaoxinxiaobai
2021-07-18 10:51:55 +08:00
放 exception handler 中统一处理
hsfzxjy
2021-07-18 11:06:04 +08:00
写成 contextmanager
plko345
2021-07-18 11:51:53 +08:00
@ericls 额,我也没想的特别清楚,就觉得虽然也能用,但似乎有更合适的办法
plko345
2021-07-18 11:53:45 +08:00
@christopheredwar 是,你说的是第一种吗?
plko345
2021-07-18 11:54:22 +08:00
@xiaoxinxiaobai 要怎么做,能否举个例子
BBCCBB
2021-07-18 13:33:30 +08:00
with 或者 装饰器 ==, 可以搞成 java spring 事务这种方式.
expkzb
2021-07-18 14:34:37 +08:00
放到 function 里不是挺好的,也就 sth 一个参数,再抛出一个 e 就行了
ipwx
2021-07-18 14:37:53 +08:00
1 2 3 4 都行
----

抛砖引玉,1:

def auto_commit(session, f):
....try:
........ret = f()
....except Exception:
........session.rollback()
........raise
....else:
........session.commit()
........return ret

auto_commit(session, lambda: session.add(sth))


2:

from functools import wraps

def auto_commit(f):
....@wraps(f)
....def wrapper(session, *args, **kwargs):
........try:
............ret = f(session)
........except Exception:
............session.rollback()
............raise
........else:
............session.commit()
............return ret
....return wrapper


@auto_commit
def my_fn(session):
........session.add(sth)

my_fn(session)
ipwx
2021-07-18 14:39:04 +08:00
3:

from contextlib import contextmanager


@contextmanager
def auto_commit(session):
....try:
........yield session
....except Exception:
........session.rollback()
........raise
....else:
........session.commit()


with auto_commit(session):
....session.add(sth)
Trim21
2021-07-18 14:52:39 +08:00
你的 session 如果不是自己封装的话很可能已经支持 with 了
plko345
2021-07-18 14:53:52 +08:00
@ipwx 大佬你的 commit 在 else 中的话, 如果 commit 失败也能 rollback 吗?
plko345
2021-07-18 14:55:51 +08:00
@Trim21 没有封装, 就是原来的 session, 如果支持的话要怎么用, 我去看看文档
Trim21
2021-07-18 14:59:39 +08:00
@plko345 #16 不知道你用得什么 ORM 框架,sqlalchemy 的话是这样的


with session.begin():
....session.add(some_object)
....session.add(some_other_object)

with 后面的代码块抛出了 exception 的话会自动 rollback
ipwx
2021-07-18 15:10:38 +08:00
@plko345 啊对,你如果有这个需求。。。那就不要放 else 呗。是我想当然了
skys215
2021-07-18 15:17:44 +08:00
没写过 flask

不是只有事务才需要用 commit ( mysql 级的)吗?
vZexc0m
2021-07-19 10:13:07 +08:00
继承 SQLAlchemy 基类,重新一个 save 方法,保存时调用 db.save()即可。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/790153

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX