在 Python 中,线程的自修复通常涉及异常处理和适当的线程管理。在线程的 run() 方法中使用 try-except 块来捕获可能发生的异常。在捕获异常后,可以记录异常信息或者尝试重新启动线程以恢复正常运行。下面看看我最近的一个实操案例。

1、问题背景

我创建了一个访问米国和欧某盟服务器的网络蜘蛛。米国和欧某盟的服务器是相同的数据结构,但内部的数据不同,我想把它们全部整理出来。为了对服务器友好,每次请求之间都会有一个等待时间。由于程序完全相同,为了加快处理速度,我将程序进行了多线程处理,以便可以同时访问欧某盟和米国服务器。这个爬取过程大约需要几周,而不是几天。会出现异常,虽然我试图在程序内部处理所有内容,但很可能会出现一些奇怪的问题。为了真正防御这个问题,我想捕获一个出现故障的线程,记录错误并重新启动它。最坏的情况是,我从数千页中丢失了几页,这比线程出现故障而损失 50% 的速度要好。然而,根据我的阅读,Python 线程会静默地死去。有没有人有什么想法?

class AccessServer(threading.Thread):
    def __init__(self, site):
        threading.Thread.__init__(self)
        self.site = site
        self.qm = QueueManager.QueueManager(site)

    def run(self):
        # Do stuff here


def main():
    us_thread = AccessServer(u"us")
    us_thread.start()

    eu_thread = AccessServer(u"eu")
    eu_thread.start()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

2、解决方案

方法一:

run 方法中使用一个 try: ... except: ... 块。如果发生某种奇怪的事情导致线程失败,很可能会在代码的某个地方抛出一个错误(而不是在多线程子系统本身中);这样你就可以捕获它,对其进行记录,并重新启动线程。是否要实际关闭线程并启动一个新线程,或者只是将 try/except 块包含在一个 while 循环中,以便同一个线程继续运行,由你决定。

方法二:

如果怀疑可能会发生一些非常奇怪的事情,而你无法通过 Python 的错误处理机制来检测到,另一个解决方案是启动一个监视线程,定期检查其他线程是否正常运行。

代码示例:

import threading
import Queue

class AccessServer(threading.Thread):
    def __init__(self, site):
        threading.Thread.__init__(self)
        self.site = site
        self.qm = QueueManager.QueueManager(site)

    def run(self):
        try:
            # Do stuff here
        except Exception as e:
            # Log the error
            print(f"Error: {e}")
            # Restart the thread
            self.run()

def main():
    us_thread = AccessServer(u"us")
    us_thread.start()

    eu_thread = AccessServer(u"eu")
    eu_thread.start()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

或者:

import threading
import time

class AccessServer(threading.Thread):
    def __init__(self, site):
        threading.Thread.__init__(self)
        self.site = site
        self.qm = QueueManager.QueueManager(site)

    def run(self):
        while True:
            try:
                # Do stuff here
            except Exception as e:
                # Log the error
                print(f"Error: {e}")
                # Restart the thread
                self.run()

def main():
    us_thread = AccessServer(u"us")
    us_thread.start()

    eu_thread = AccessServer(u"eu")
    eu_thread.start()

def monitor_threads():
    while True:
        # Check if the threads are still running
        if not us_thread.is_alive() or not eu_thread.is_alive():
            # Restart the threads
            us_thread = AccessServer(u"us")
            us_thread.start()

            eu_thread = AccessServer(u"eu")
            eu_thread.start()

        # Sleep for a bit
        time.sleep(1)

# Start the monitor thread
monitor_thread = threading.Thread(target=monitor_threads)
monitor_thread.start()
  • 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.

通过上面的这些方法,最终我们可以在 Python 中实现一定程度的线程自修复功能,确保线程在遇到异常时能够进行适当的处理,从而提高程序的稳定性和可靠性。