顺便学了下python的装饰器函数

装饰器原理:

其实就是把函数传到decorator中,然后将wrap函数返回给传进去的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def a_new_decorator(a_func):

def wrapTheFunction():
print("I am doing some boring work before executing a_func()")

a_func()

print("I am doing some boring work after executing a_func()")

return wrapTheFunction

def a_function_requiring_decoration():
print("I am the function which needs some decoration to remove my foul smell")

a_function_requiring_decoration()
#outputs: "I am the function which needs some decoration to remove my foul smell"

a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
#now a_function_requiring_decoration is wrapped by wrapTheFunction()

a_function_requiring_decoration()

然后python提供了一个语法糖,可以将a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)这句优雅地写成@a_new_decorator


代码如下,暂时只写了这些,以后会逐步完善。

先实例化一个类,然后这个类的实例替代requests,主要是用装饰器添加了异常捕获

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 装饰器函数

def exceptDecoration(func):

# 在这里添加self参数,可以使用类中的变量
def wrapper(self, *args, **kwargs):
retrieveCount = 0
while(retrieveCount < 5):
try:
# 被装饰的函数
response = func(self, *args, **kwargs)
# 手动抛出HTTP异常
response.raise_for_status()
# 推测编码
encoding = cchardet.detect(response.content)['encoding']
response.encoding = encoding

return response
except requests.exceptions.HTTPError as err:
print('错误码:%d\n%s' % (err.response.status_code))
return err.response.status_code
except requests.RequestException as err:
delay = random.randrange(1, 4)
print('%s\n延迟%d秒后重试 第%d次...' %
(err, delay, retrieveCount))
time.sleep(delay)
print('重试...')
finally:
retrieveCount += 1

return wrapper

class AskUrl():
def __init__(self, *args, **kwargs):
self.__args = args
self.__kwargs = kwargs
if 'headers' not in self.__kwargs:
self.__kwargs['headers'] = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3775.400 QQBrowser/10.6.4208.400'
}
if 'method' not in self.__kwargs:
self.__kwargs['method'] = 'GET'

# 默认超时15秒
if 'timeout' not in self.__kwargs:
self.__kwargs['timeout'] = 20

self.__session = None

# 通过装饰器函数添加异常捕捉

@exceptDecoration
def request(self, *args, **kwargs):
self.__updatePrams(*args, **kwargs)
# 返回 在装饰器中用,元组和字典需要解一下传参
return requests.request(*self.__args, **self.__kwargs)

@exceptDecoration
def session(self, *args, **kwargs):
self.__updatePrams(*args, **kwargs)
self.__session = requests.session()
return self.__session.request(*self.__args, **self.__kwargs)

def getSession(self):
if not self.__session:
print('必须先获得session对象')
return None
return self.__session

# 此函数需要传入可变参数,不可直接传元组和字典
def __updatePrams(self, *args, **kwargs):
if(args):
self.__args = (*self.__args, *args)
if(kwargs):
self.__kwargs.update(kwargs)

def reset(self, *args, **kwargs):
self.__args = args
self.__kwargs = kwargs

askUrl = AskUrl()