软硬件开发技术笔记
保持专注,拒绝内耗
python2和python3中hasattr的区别
2021-10-12 00:39

分析hasattr在python2/python3下遇到的不同行为的问题

先说结论:
python2和python3的hasattr实现,实际是调用getattr,然后判断是否会抛出异常,如果抛出异常,则判定为没有指定的属性返回false,否则返回true。但是python2会捕获所有的异常,而python3仅捕获PyExc_AttributeError异常,其他异常会继续向上抛,导致上层逻辑收到异常。

相关依据:
python2的hasattr文档描述看这里,代码实现看这里
python3的hasattr文档描述看这里,代码实现看这里

代码例子:

class Test(object):
    a = "this is a"

    def __init__(self):
        self.b = "this is b"

    def c(self):
        print("this is c")
        x=1/0

    @property
    def d(self):
        print("this is d")
        x=1/0

test = Test()


print("a" in dir(test))
print("b" in dir(test))
print("c" in dir(test))
print("e" in dir(test))
print("d" in dir(test))

python2输出

近期遇到一个python2和python3在处理flask逻辑的坑,代码如下,在路由中判断是否传入json数据。

import flask
...
@app.route(...)
def test():
    ...
    print(hasattr(request, 'json'))
    ...
...

python2的表现:可以正常返回true/false
python3的表现,抛出如下异常:

Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "api.py", line 1485, in test
    print(hasattr(request, 'json'))
  File "/usr/lib/python3.6/site-packages/werkzeug/local.py", line 347, in __getattr__
    return getattr(self._get_current_object(), name)
  File "/usr/lib/python3.6/site-packages/flask/wrappers.py", line 108, in json
    return self.get_json()
  File "/usr/lib/python3.6/site-packages/flask/wrappers.py", line 155, in get_json
    rv = self.on_json_loading_failed(e)
  File "/usr/lib/python3.6/site-packages/flask/wrappers.py", line 174, in on_json_loading_failed
    raise BadRequest('Failed to decode JSON object: {0}'.format(e))
werkzeug.exceptions.BadRequest: 400 Bad Request: Failed to decode JSON object: Expecting value: line 1 column 1 (char 0)
分类
mac
1篇
4篇
c
1篇
4篇
2篇
1篇
搜索