2011-12-25 347 views
2

我有一個網頁爬行python腳本在終端運行了幾個小時,這是不斷填充我的數據庫。它有幾個嵌套for循環。出於某些原因,我需要重新啓動計算機,並從我離開的地方繼續執行我的腳本。是否可以保持指針狀態並恢復終端中以前運行的腳本?如何暫停在終端運行的python腳本

我正在尋找一種解決方案,它將在不改變python腳本的情況下工作。修改代碼的優先級較低,因爲這意味着重新啓動程序並重新投入時間。

更新: 感謝VM的建議。我會採取的。爲了完成,應該對腳本進行什麼樣的通用修改以使其暫停和恢復?

Update2: VM上的移植工作正常。我還修改了腳本,使其能夠防止網絡故障。代碼如下。

+2

休眠你的電腦! – Hossein 2011-12-25 17:10:41

+1

在虛擬機中運行它。 – 2011-12-25 17:16:16

+0

@Hossein我的Mac不支持休眠:(而且我不認爲從休眠狀態恢復將恢復我的爬行腳本正確 – jerrymouse 2011-12-25 17:42:42

回答

3

您可能嘗試暫停計算機或在虛擬機中運行,隨後可能會暫停計算機。但是,當您的腳本正在使用網絡連接時,一旦您啓動系統後,您的腳本將無法運行。暫停計算機並恢復它或保存虛擬M/C並恢復它意味着您需要重新建立網絡連接。對於系統外部的任何元素都是如此,網絡就是其中之一。如果你使用的是動態網絡,那麼很有可能你下次開機的時候會得到一個新的IP,而你以前工作的網絡狀態將是無效的。

如果您打算修改腳本,您需要保留一些注意事項。

  1. 添加序列化和反序列化功能。 Python有醃菜和更快的cPickle方法來做到這一點。
  2. 添加重新開始分。這樣做的最好方法是定期保存狀態,並在重新啓動腳本時,在建立所有瞬態元素(如網絡)後,從上次保存的狀態重新啓動。

這不會是一件容易的任務,以便考慮投資的時間considrable量:-)

注意***

退一步。有一種方法可以改變腳本。您可以嘗試使用雲端虛擬化解決方案,如Amazon EC2。

1

正如其他人所評論的,除非您在可以掛起的虛擬機中運行腳本,否則您需要修改腳本以跟蹤其狀態。

0

如果此問題足夠重要以保證這種財務投資,則可以在虛擬機上運行腳本。當您需要關閉時,暫停虛擬機,然後關閉計算機。當您想再次啓動時,啓動計算機,然後喚醒虛擬機。

+0

您是否嘗試過這種?網絡和數據庫連接怎麼樣? – reclosedev 2011-12-25 17:28:54

+0

@reclosedev我還沒試過。讓腳本運行一段時間,然後將其移植到VM並重試。 – jerrymouse 2011-12-25 17:47:51

0

WinPDB是一個支持遠程調試的python調試器。我從來沒有使用它,不知道是否遠程調試正在運行的進程需要對腳本進行修改(這很可能會導致安全問題);但如果在不修改腳本的情況下進行遠程調試是可能的,那麼您可能能夠將腳本的當前狀態轉儲到文件中,並在以後找出如何加載它。我不認爲它會工作。

1

由於您正在使用您的數據填充數據庫,因此我建議將其用作跟蹤腳本進度的方式(獲取最新的URL解析,獲取掛起的URL列表等)。

如果腳本突然終止,您不必擔心保存其狀態,因爲數據庫事務將救援並且只有您提交的數據將被保存。

腳本重新啓動後,只會存儲完整處理的URL的數據,您可以繼續根據數據庫提取下一個URL。

1

我將腳本移植到VM並從那裏啓動它。但是,從休眠狀態恢復後出現網絡連接故障。下面是我如何解決它通過調整python腳本:

import logging 
import socket 
import time 
socket.setdefaulttimeout(30) #set timeout in secs 
maxretry = 10 #set max retries 
sleeptime_between_retry = 1 #waiting time between retries 

erroroccured = 0 
while True: 
    try: 
     domroot = parse(urllib2.urlopen(myurl)).getroot() 
    except Exception as e: 
     erroroccured += 1 
     if erroroccured>maxretry: 
      logger.info("Maximum retries reached. Quitting this leg.") 
      break 
     time.sleep(sleeptime_between_retry) 
     logging.info("Network error occurred. Retrying %d time..."%(erroroccured)) 
     continue 
    finally: 
     #common code to execute after try or except block, if any 
     pass 
    break 

這一修改使我的腳本證明脾氣網絡故障。