python線程池、自定義異常、請求僞裝

線程池概念:

線程池可以理解爲一個裝載多線程的池子,池中放置了指定數量的線程,當我們提交的任務超過線程池的數量時,多餘的任務會進行排隊等待,待其他任務執行完畢後,再將隊列中的任務提交到線程執行,線程池的好處是,能同時執行多個任務,複用線程資源,減少線程的創建和銷燬,更節約系統資源。

1.普通代碼,理論是在一個線程執行任務,和其他語言類似,代碼從上至下依次執行。

import time


def test_data(index):
    time.sleep(5)
    if index % 2 == 0:
        print(f'{index}執行錯誤。')
        raise Exception('我報錯了')
    print(f'{index}執行完畢。')

for i in range(1, 50):
    test_data(i)
  • 輸出:

1執行完畢。
Traceback (most recent call last):
  File "/Users/peakchao/Code/Py/ReptileForPython/pool_test.py", line 15, in <module>
    test_data(i)
  File "/Users/peakchao/Code/Py/ReptileForPython/pool_test.py", line 11, in test_data
    raise Exception('我報錯了')
Exception: 我報錯了
2執行錯誤。

分析:循環調用test_data方法,test_data方法中睡眠5秒後對傳入的值進行取餘,如果餘數爲0,則拋出異常,當i=1時,程序正常執行,在第二次循環時,i==2,取餘等於0,拋出異常,程序崩潰退出。

注意:此時每過5秒才能打印依次。

2.多線程代碼,理論是多個線程同時執行任務,線程池在不同語言中都有相似的實現。

import time
from concurrent.futures import ThreadPoolExecutor

pool = ThreadPoolExecutor(max_workers=2)


def test_data(index):
    time.sleep(5)
    if index % 2 == 0:
        print(f'{index}執行錯誤。')
        raise Exception('我報錯了')
    print(f'{index}執行完畢。')


for i in range(0, 50):
    pool.submit(test_data, i)
  • 輸出:

1執行完畢。0執行錯誤。

3執行完畢。
2執行錯誤。
4執行錯誤。
5執行完畢。
6執行錯誤。
7執行完畢。

分析:同一時刻有2個打印,說明有2個任務在並行,如果我們把線程池數量改爲n,那麼他的執行效率是單線程的n倍。

請求僞裝:

有時我們抓取網站數據時,服務器會返回錯誤,而我們使用瀏覽器訪問卻又能正常打開,是因爲服務器分析了我們的請求數據,判斷出我們是爬蟲,所以終止了正常響應,當我們頻繁抓取某個網站數據時,即使設置了請求僞裝也會偶有失敗,是因爲請求信息固定,且有規律所以被攔截。

USER_AGENTS = [
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Safari/605.1.15',
    'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1',
    'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1',
    'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Mobile Safari/537.36'
]


def get_request_headers():
    headers = {
        'User-Agent': random.choice(USER_AGENTS),
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
        'Accept-language': 'zh-CN,zh;q=0.9',
        'Accept-Encoding': 'gzip, deflate,br',
        'Connection': 'keep-alive',
    }
    return headers

自定義異常:

往往系統定義的異常不能滿足需求,爲了拋出更明確的錯誤,以及後續對自己想要的錯誤進行攔截處理,我們需要自定義異常。

class BaseException(Exception):
    def __init__(self, msg):
        self.msg = msg

    def __str__(self):
        print(self.msg)


try:
    input_data = input('請輸入:')
    if len(input_data) > 0:
        raise BaseException('哈哈,不允許輸入任何文字哦~')
    print('執行完畢')
except BaseException as err:
    print(f'捕捉到自定義異常:{err}')
  • 輸出:

請輸入:666
哈哈,不允許輸入任何文字哦~
哈哈,不允許輸入任何文字哦~
Traceback (most recent call last):
  File "/Users/peakchao/Code/Py/ReptileForPython/pool_test.py", line 30, in <module>
    raise BaseException('哈哈,不允許輸入任何文字哦~')
__main__.BaseException: <exception str() failed>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/peakchao/Code/Py/ReptileForPython/pool_test.py", line 33, in <module>
    print(f'捕捉到自定義異常:{err}')
TypeError: __str__ returned non-string (type NoneType)

Process finished with exit code 1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章