Python 异常处理风格 - V2EX
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
bbxiong
V2EX    Python

Python 异常处理风格

  •  
  •   bbxiong 2020-11-20 12:21:00 +08:00 3019 次点击
    这是一个创建于 1831 天前的主题,其中的信息可能已经有所发展或是发生改变。

    selenium api 基本全都会抛异常

    比如

    if driver.find_element_by_class_name("general-error"): print("登录错误")

    必须要写成如下 try: if driver.find_element_by_class_name("general-error"): print("登录错误") except: pass

    所有常用 api 都会抛出异常,每个 find_element_by_xxx 都必须放在 try except 封装成函数,显得代码臃肿不堪...

    是不是我的风格有问题,请教下大家都怎么处理这种情况的.

    第 1 条附言    2020-11-20 13:00:17 +08:00

    循环登录代码

     while True: if driver.find_element_by_class_name("loaderIcon"): print("网页加载中") time.sleep(1) elif driver.find_element_by_class_name("ut-tab-bar"): print("登陆成功") return True elif driver.find_element_by_class_name("btn-standard"): driver.find_element_by_class_name("btn-standard").click() WebDriverWait(driver, 1).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "btnLogin"))) if driver.find_element_by_id("btnLogin"): print("找到 btnLogin") break elif driver.find_element_by_id("email"): driver.find_element_by_id("email").send_keys(username) driver.find_element_by_id("password").send_keys(pwd) driver.find_element_by_id("btnLogin").click() elif driver.find_element_by_id("btnSendCode"): print("等待输入验证码") elif driver.find_element_by_class_name("general-error"): print("登陆错误!!!") break 

    必须要吧每个find_element_xxx 封装函数,内部try catch处理,代码量增加不少

    while True: if 是否加载中(): print("网页加载中") time.sleep(1) elif 登陆成功(): print("登陆成功") return True elif 是否登录界面(): driver.find_element_by_class_name("btn-standard").click() WebDriverWait(driver, 1).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "btnLogin"))) if driver.find_element_by_id("btnLogin"): print("找到 btnLogin") break elif 是否输入用户名密码界面(): driver.find_element_by_id("email").send_keys(username) driver.find_element_by_id("password").send_keys(pwd) driver.find_element_by_id("btnLogin").click() elif 是否验证码界面(): print("等待输入验证码") elif 登陆错误(1): print("登陆错误!!!") break 
    8 条回复    2020-11-25 19:24:09 +08:00
    imn1
        1
    imn1  
       2020-11-20 12:32:26 +08:00
    这种情况我选择换个写法,例如其他模块

    实际上我都没用过 selenium api,都不知道会抛出异常,我是获取 content 然后用其他 prser 模块处理的

    如果不可避免非要用某个模块,它又容易抛出异常,我会写个类继承过来,或者闭包,把异常集中处理
    happinessnch
        2
    happinessnch  
       2020-11-20 12:37:47 +08:00
    异常处理,和业务逻辑没有关系,咋一看好像很臃肿,好多地方要 try catch,
    实际上异常处理多了慢慢也就习惯了,根据不同异常做一些定制化的处理,
    绝大多数异常是不应该直接 pass 的,但是实际开发时,每个异常都处理确实有点过于苛求了。
    no1xsyzy
        3
    no1xsyzy  
       2020-11-20 14:25:40 +08:00
    这个是设计问题,不过你这边似乎也可以更正交地抽象

    def finds(driver, **kwargs):
       try:
         return driver.find_element(...) # TODO: implement it
       except:
         return None

    这样的话你以后就可以
    if finds(driver, class_name="loaderIcon"):
      ...
    elif finds(driver, class_name="ut-tab-bar"):
      ...
    ...
    no1xsyzy
        4
    no1xsyzy  
       2020-11-20 14:28:58 +08:00
    @happinessnch BTW 如果逻辑上确实应不处理,我推荐 with contextlib.suppress
    如果暂时不作处理,我推荐 except: pass # TODO: handle this
    bbxiong
        5
    bbxiong  
    OP
       2020-11-20 15:13:14 +08:00
    @no1xsyzy 这种设计方式用起来比较方便,其实我奇怪的为啥 selenium 设计这些 api 要抛异常,而不是找不到返回 None
    imn1
        6
    imn1  
       2020-11-20 15:24:16 +08:00
    @bbxiong #5
    模块一般是通用的,泛考虑

    例如某个 exif 模块,里面严格执行 exif 规范,dump 的时候一个值错了就会抛异常
    本来 exif 有几百条,一条错误并不影响其他读取,也不影响图片本身显示,批量处理(上千个图片)遇到错误可以跳过就行了,逐个处理异常确实麻烦
    但人家按照规范做,也不能说人家做错了,因为遵守规范总是正确立场,只能自己继承修改以适应自己的需求
    no1xsyzy
        7
    no1xsyzy  
       2020-11-20 22:38:38 +08:00
    @bbxiong 发现我可能单位写了一堆忘了发……
    应该它的这些 API 就是设计为链式调用的,那显然报一个“元素找不到”的错比“NoneType 没有此属性”的错更合理。
    不过,我设计的话会设计两套 API,一个更简洁的引发异常,更嗦的给 None,形如 dct['key'] v.s. dct.get('key')
    或者提供一个参数来表示默认值,不提供就引发异常,形如 dct.pop('key', None) v.s. dct.pop('key')
    peckey
        8
    peckey  
       2020-11-25 19:24:09 +08:00
    find_elements_by_xxx 不会抛出异常
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3763 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 00:53 PVG 08:53 LAX 16:53 JFK 19:53
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86