在 Python 中重新启动线程

2024-01-31

我正在尝试为 Python 3.4 中的一个项目制作线程飞行软件,其中我需要线程自行重新启动,以防在传感器读取期间发生 I/O 错误或类似的意外崩溃。因此,我正在努力制作一个看门狗来检查线程是否已死亡并重新启动它们。

起初,我尝试检查线程是否不再活动并重新启动它,这样做是这样的:

>>> if not a_thread.isAlive():
...     a_thread.start()
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "c:\Python34\lib\threading.py", line 847, in start
    raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once

从以下角度来看,这种行为是有道理的threading和 Python 本身,但这让我的工作变得更加困难。因此,我实现了一个解决方案,使用字典来存储初始线程并将其复制到新对象并在必要时启动它。不幸的是这也不起作用。 这是一个基本示例:

import threading
import logging
import queue
import time
from copy import copy, deepcopy

def a():
    print("I'm thread a")
def b():
    print("I'm thread b")

# Create thread objects
thread_dict = {
'a': threading.Thread(target=a, name='a'),
'b': threading.Thread(target=b, name='b')
}

threads = [copy(t) for t in thread_dict.values()]

for t in threads:
    t.start()
for i in range(len(threads)):
    if not threads[i].isAlive():
        temp = thread_dict[threads[i].name]
        threads[i] = deepcopy(temp)
        threads[i].start()
    thread(i).join(5)

返回:

I'm thread a
I'm thread b
Traceback (most recent call last):
  File "main_test.py", line 25, in <module>
    threads[i] = deepcopy(temp)
  File "c:\Python34\lib\copy.py", line 182, in deepcopy
    y = _reconstruct(x, rv, 1, memo)
  ... (there's about 20 lines of traceback within copy)
  File "c:\Python34\lib\copyreg.py", line 88, in __newobj__
    return cls.__new__(cls, *args)
TypeError: object.__new__(_thread.lock) is not safe, use _thread.lock.__new__()

所以显然threading对象复制不安全...是否有办法重新启动线程而不重新创建整个对象?


没有理由让你的线程死掉。

如果它们真的崩溃了,你的整个程序也会崩溃。

如果他们只是引发异常,您只需捕获异常即可。

如果他们正常返回,你就可以不这样做。

您甚至可以简单地包装线程函数以在异常或返回时重新启动自身:

def threadwrap(threadfunc):
    def wrapper():
        while True:
            try:
                threadfunc()
            except BaseException as e:
                print('{!r}; restarting thread'.format(e))
            else:
                print('exited normally, bad thread; restarting')
    return wrapper

thread_dict = {
    'a': threading.Thread(target=wrapper(a), name='a'),
    'b': threading.Thread(target=wrapper(b), name='b')
}    

问题解决了。


您无法重新启动线程。

大多数平台都没有办法这样做。

从概念上讲,它没有任何意义。当一个线程结束时,它的堆栈就死了;其父级被标记或发出信号;一旦它加入,它的资源就会被销毁(包括内核级资源,如进程表条目)。重新启动它的唯一方法是创建一套全新的一切。您已经可以通过创建新线程来做到这一点。

所以,就这么做吧。如果您确实不想在内部处理异常,只需存储构造参数并使用它们来启动新线程即可。

您甚至可以创建自己的子类来为您挂载它们:

class RestartableThread(threading.Thread):
    def __init__(self, *args, **kwargs):
        self._args, self._kwargs = args, kwargs
        super().__init__(*args, **kwargs)
    def clone(self):
        return RestartableThread(*self._args, **self._kwargs)

现在很容易“复制”线程(使用您想要的语义):

if not a_thread.is_alive():
    a_thread = a_thread.clone()

Yes, threading.Thread对象复制不安全

您期望发生什么?最好的情况是,你会在同一个操作系统级线程对象周围得到一个不同的包装器,这样你就可以欺骗Python,让它没有注意到你正在尝试做一些非法的、可能引发段错误的事情,而它试图阻止你这样做。正在做。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Python 中重新启动线程 的相关文章

随机推荐

  • C# RSA 无填充

    我正忙着尝试移植如下所示的 Java 代码 Cipher rsa Cipher getInstance RSA ECB nopadding rsa init Cipher DECRYPT MODE RSAPrivateKey decrypt
  • Gson 使用存根序列化循环引用

    我正在尝试实现一些简单的 Json 序列化功能 但我很难应对 Gson 的巨大复杂性 所以基本上我有一堆实体类 它们通过大量循环引用相互引用 为了将此结构序列化为 JSON 我想跟踪已序列化的对象 实体类都实现了一个名为Identified
  • Scala 向后兼容性

    哪些变化或代码演变破坏了向后兼容性 主要是二进制兼容性 是否已在任何地方完全指定 我检查了Scala 语言规范 http www scala lang org docu files ScalaReference pdf 但没有看到任何关于此
  • 从特征序列化分解矩阵(SparseLU 对象)

    我正在尝试解决Ax b其中矩阵 A 可以大到接近1M x 1M在大小上 是稀疏且对称的 但可能没有明确定义 问题是使用以下方法计算分解可能需要很长时间稀疏LU对象 http eigen tuxfamily org dox devel cla
  • PPModel.php 第 51 行中的 PayPal REST API 问题

    每当我尝试使用 create php 在 paypal 上创建付款时 都会出现此错误 致命错误 找不到类 string public html demos demo files integrate paypal rest api php m
  • 删除观察者

    在 NSManagedObject 子类中 我有代码 void awakeFromInsert self addObserver NSApp delegate forKeyPath name options NSKeyValueObserv
  • Lombok/Jackson - 用于 json 数组的 POJO

    我有一个 json 数组 需要从服务器接收 反序列化 并将其发送 序列化 到另一台服务器 Example car name string parts engine wheels 我开始编写以下 POJO 来表示这个 Json 数组 impo
  • 从会话存储文件中读取会话数据

    面临问题PHP unserialize 函数如标题所示 它抛出错误 unserialize function unserialize Error at offset 0 of 1781 bytes 我也尝试过session decode 返
  • 如何将详细垃圾收集输出重定向到文件?

    如何将详细垃圾收集输出重定向到文件 Sun 的网站显示了 Unix 的示例 但不适用于 Windows 从输出java X Xloggc
  • 如何将从请求生成的 xml 结构转换为 Web 服务

    我有一个字符串 var 用于存储来自对 RESTful 服务的请求的 xml 我在使用 xslt 文件动态转换此文件而不保存它时遇到问题 我收到这个错误 System UriFormatException Invalid URI The U
  • C# 在 application.run() 之后执行代码

    我有一个与此类似的问题 表单启动后如何执行代码 https stackoverflow com questions 4100428 how can i execute code after my form starts 但那里的解决方案对我
  • 是否可以将 Protobuf-Net 与没有无参数构造函数的类一起使用?

    使用 Protobuf Net 我发现在没有无参数构造函数的情况下似乎不可能反序列化一个类 或者我可能会丢失一些东西 我不想要一些带有无参数构造函数的类 我可以使用某种属性或其他技术吗 protobuf net 目前依赖于无参数构造函数的工
  • 缩略图/图像缓存文件?

    为了为我正在编写的应用程序提供更好的安全性和隐私性 我将删除在 Android 设备上找到的图像和图片 因此 我很想知道操作系统是否创建了任何缓存 缩略图文件 例如 以便图库应用程序可以在处理完整的实际文件之前显示快速预览 如果创建了此类文
  • 关于Python Flask 500 Internal Server Error的问题

    这是我的Python代码 from flask import Flask render template app Flask name app route profile
  • 逐渐淡化图片

    此功能的想法是仅淡化图片的上半部分 使其逐渐变暗 这是我所拥有的 但它似乎使所有上半部分变成纯黑色 def fadeDownFromBlack pic1 w getWidth pic1 h getHeight pic1 for y in r
  • 为什么我的 Heroku 应用程序无法在生产环境中使用 Sendgrid 发送电子邮件?

    我的设计电子邮件在开发中运行良好 但现在我已经推送到 Heroku 并正在使用 sendgrid 插件 它们没有被发送 我没有收到错误 看起来它发送得很好 只是它从未真正到达我的收件箱 这是我的config environment prod
  • 按最大日期分组

    我在执行这段代码时遇到问题 SELECT FROM tblpm n WHERE date updated SELECT MAX date updated FROM tblpm GROUP BY control number HAVING c
  • SQL Server 对 OrmLite 的特定类型支持

    我刚刚了解了一种天才类型 它可以简化我的很多工作 但看起来我喜欢的 ORM 无法识别它 有没有办法让 ServiceStack OrmLite 识别HierarchyId在 SQL Server 中 关于要修改哪些文件的任何建议以及如何继续
  • 停止 Xcode 自动为 Objective-C 标头生成 Swift 接口

    是否可以在显示 Objective C 标头时阻止 Xcode 8 自动生成 Swift 界面 例如通过设置用户默认值 从理论上讲 这是 Xcode 的一个非常好的功能 不幸的是它不能可靠地工作 对我来说 大多数时候它甚至似乎都失败了 由于
  • 在 Python 中重新启动线程

    我正在尝试为 Python 3 4 中的一个项目制作线程飞行软件 其中我需要线程自行重新启动 以防在传感器读取期间发生 I O 错误或类似的意外崩溃 因此 我正在努力制作一个看门狗来检查线程是否已死亡并重新启动它们 起初 我尝试检查线程是否