V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
plko345
V2EX  ›  Python

大量的 try 应该怎么复用

  •  
  •   plko345 · 2021-07-18 08:45:16 +08:00 via Android · 4702 次点击
    这是一个创建于 1223 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    
    # ...
    
    try:
    
        session.add(sth)
    
        session.commit()
    
    except Exception as e:
    
        session.rollback()
    
        raise e
    
    

    我的一些想法

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

    2. 装...装饰器

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

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

    20 条回复    2021-07-19 10:13:07 +08:00
    MintZX
        1
    MintZX  
       2021-07-18 09:12:59 +08:00
    2 4 都行啊
    ericls
        2
    ericls  
       2021-07-18 09:15:18 +08:00
    为什么 function 不好?
    learningman
        3
    learningman  
       2021-07-18 10:25:33 +08:00   ❤️ 1
    with 最好了,自己重载一个 ContextManager
    christopheredwar
        4
    christopheredwar  
       2021-07-18 10:39:14 +08:00
    是 sqlalchemy 麽,可以封装成一个函数,传 kwargs,往里传参数就好。
    xiaoxinxiaobai
        5
    xiaoxinxiaobai  
       2021-07-18 10:51:55 +08:00 via Android
    放 exception handler 中统一处理
    hsfzxjy
        6
    hsfzxjy  
       2021-07-18 11:06:04 +08:00 via Android   ❤️ 1
    写成 contextmanager
    plko345
        7
    plko345  
    OP
       2021-07-18 11:51:53 +08:00 via Android
    @ericls 额,我也没想的特别清楚,就觉得虽然也能用,但似乎有更合适的办法
    plko345
        8
    plko345  
    OP
       2021-07-18 11:53:45 +08:00 via Android   ❤️ 1
    @christopheredwar 是,你说的是第一种吗?
    plko345
        9
    plko345  
    OP
       2021-07-18 11:54:22 +08:00 via Android
    @xiaoxinxiaobai 要怎么做,能否举个例子
    BBCCBB
        10
    BBCCBB  
       2021-07-18 13:33:30 +08:00
    with 或者 装饰器 ==, 可以搞成 java spring 事务这种方式.
    expkzb
        11
    expkzb  
       2021-07-18 14:34:37 +08:00 via Android
    放到 function 里不是挺好的,也就 sth 一个参数,再抛出一个 e 就行了
    ipwx
        12
    ipwx  
       2021-07-18 14:37:53 +08:00   ❤️ 2
    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
        13
    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
        14
    Trim21  
       2021-07-18 14:52:39 +08:00 via Android
    你的 session 如果不是自己封装的话很可能已经支持 with 了
    plko345
        15
    plko345  
    OP
       2021-07-18 14:53:52 +08:00
    @ipwx 大佬你的 commit 在 else 中的话, 如果 commit 失败也能 rollback 吗?
    plko345
        16
    plko345  
    OP
       2021-07-18 14:55:51 +08:00
    @Trim21 没有封装, 就是原来的 session, 如果支持的话要怎么用, 我去看看文档
    Trim21
        17
    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
        18
    ipwx  
       2021-07-18 15:10:38 +08:00
    @plko345 啊对,你如果有这个需求。。。那就不要放 else 呗。是我想当然了
    skys215
        19
    skys215  
       2021-07-18 15:17:44 +08:00
    没写过 flask

    不是只有事务才需要用 commit ( mysql 级的)吗?
    vZexc0m
        20
    vZexc0m  
       2021-07-19 10:13:07 +08:00   ❤️ 1
    继承 SQLAlchemy 基类,重新一个 save 方法,保存时调用 db.save()即可。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4650 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 01:07 · PVG 09:07 · LAX 17:07 · JFK 20:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.