使用py-spy解決scrapy卡死的問題方法
背景
在使用scrapy爬取東西的時候,使用crontab定時的啟動爬蟲,但是發現機器上經常產生很多卡死的scrapy程序,一段時間不管的話,會導致有10幾個程序都卡死在那,並且會導致資料產出延遲。
問題定位
使用py-spy這個非常好用的python效能分析工具來進行排查,py-spy可以檢視一個python程序函式呼叫用時,類似unix下的top命令。所以我們用這個工具看看是什麼函式一直在執行。
首先安裝這個工具
pip install py-spy
用py-spy看看scrapy哪個函式執行時間長
# 先找到這個卡死的scrapy程序的pid ps -ef |grep scrapy # 啟動 py-spy 觀察這程序 py-spy top --pid 53424
首先我們按3,按OwnTime進行排序,這個表示函式自身執行的時間,可以看到read這個函式執行的時間最長,那看來是IO導致的,程式中的IO行為就是讀寫磁碟和網路IO,磁碟讀寫一般不會有問題,所以初步定位是網路IO導致的。
接下來進行進一步確認,再按4,按TotalTIme 所有子函式執行時間總和進行排序,可以看到是在process_item和download,upload_image這些主流程函式的執行時間比較長,這一步是先把圖片下載到本地,然後上傳到靜床,看來是下載這步從網路中read資料時出現了問題,進一步追蹤程式碼。
看下download的函式的程式碼:
if filename == '': filename = os.path.basename(url) path = path + '/' + filename try: res = request.urlretrieve(url,filename=path) print(url,res) return path except Exception as e: print('download img failed') print(e) return False
可以看到用了urllib這個庫裡面request.urlretrieve函式,這個函式是用來下載檔案的,去看看python官網文件的函式說明,發現裡面沒有超時時間這個引數,所以是由於沒有超時時間,導致一直在read,進而使得程序卡死。
urllib.request.urlretrieve(url,filename=None,reporthook=None,data=None)
解決方案
使用另一種方式來下載圖片,使用支援超時時間的urlopen函式,封裝成一個自定義的url_retrieve,這樣就不再會出現沒有超時導致的卡死問題了。
def url_retrieve(self,url,path): r = request.urlopen(url,timeout=5) res = False with open(path,"wb") as f: res = f.write(r.read()) f.flush() f.close() return res
到此這篇關於使用py-spy解決scrapy卡死的問題方法的文章就介紹到這了,更多相關scrapy卡死內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!