如何在终端中暂停运行的Python脚本

3
我有一个在终端运行了数小时的网页爬取Python脚本,它不断地向我的数据库中添加数据。它有几个嵌套的for循环。由于某些原因,我需要重新启动计算机,并从我离开的地方继续我的脚本。是否可能保留指针状态并恢复之前在终端运行的脚本?
我正在寻找一种解决方案,可以在不修改Python脚本的情况下工作。修改代码的优先级较低,因为这意味着要重新启动程序并投入时间。
更新: 感谢虚拟机建议。我会采用那个。为了完整起见,应对脚本进行哪些通用修改以使其暂停和可恢复?
更新2: 在虚拟机上移植工作正常。我还修改了脚本,使其能够应对网络故障。以下是修改后的代码。

2
让你的电脑休眠! - Hossein
@Hossein,我的Mac不支持休眠:(。此外,我认为从休眠中恢复可能无法正确地恢复我的爬虫脚本。 - jerrymouse
6个回答

4
您可以尝试暂停计算机或在虚拟机中运行,然后可以暂停虚拟机。但是,由于您的脚本涉及网络连接,所以可能会出现从您离开的那一点开始您的脚本无法工作的情况。暂停计算机并还原它或保存虚拟M / C并还原它意味着您需要重新建立网络连接。对于任何外部于您的系统的元素都是如此,而网络就是其中之一。而且,如果您使用的是动态网络,则下次启动时很有可能会获得新的IP地址,您之前工作的网络状态将无效。
如果您打算修改脚本,请记住以下几点:
1. 添加序列化和反序列化功能。 Python有pickle和更快的cPickle方法来执行此操作。 2. 添加重启点。最好的方法是定期保存状态,并在重新启动脚本时,在建立所有瞬态元素(如网络)后从最后保存的状态重新启动。
这不是一项容易的任务,因此请考虑投入相当多的时间:-)
注意***
再考虑一下。有一种另类的选择可以避免更改脚本。您可以尝试使用云虚拟化解决方案,如Amazon EC2。

2

我将我的脚本移植到虚拟机并从那里启动它。然而,在从休眠状态恢复后,出现了网络连接故障。以下是我通过调整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

这个修改让我的脚本不受网络故障的影响。

1

正如其他人所评论的,除非你在可以暂停的虚拟机中运行你的脚本,否则你需要修改你的脚本来跟踪其状态。


1

既然您正在使用数据库填充数据,我建议将其用作跟踪脚本进度的方式(获取最新解析的URL,拥有待处理的URL列表等)。

如果脚本突然终止,您无需担心保存其状态,因为数据库事务会挽救局面,只有您提交的数据才会被保存。

当脚本重新启动时,仅存储您完全处理的URL数据,并且可以根据数据库选择下一个要处理的URL以便恢复执行。


0
如果这个问题很重要,需要进行这种财务投资,您可以在虚拟机上运行脚本。当您需要关闭时,暂停虚拟机,然后关闭计算机。当您想要重新启动时,启动计算机,然后唤醒您的虚拟机即可。

你试过这个吗?网络和数据库连接怎么样? - reclosedev
@reclosedev 我还没有尝试过。我会让脚本运行一段时间,然后将其移植到虚拟机上并重试。 - jerrymouse

0

WinPDB是一个支持远程调试的Python调试器。我从未使用过它,也不知道是否需要修改脚本来远程调试正在运行的进程(很可能需要修改,否则会存在安全问题);但如果可以在不修改脚本的情况下进行远程调试,则您可以将脚本的当前状态转储到文件中,并稍后找出如何加载它。不过我认为这种方法可能行不通。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接