Inhaltsverzeichnis
Richtige Antwort
Heim Backend-Entwicklung Python-Tutorial Kontextmanager und Daemon-Threads

Kontextmanager und Daemon-Threads

Feb 06, 2024 am 11:27 AM

Kontextmanager und Daemon-Threads

Frageinhalt

Ich starte einen Daemon-Thread von einem Kontextmanager, der jede Sekunde einen Heartbeat senden soll, aber da er in einem Thread läuft, beendet er den Kontextmanager nicht, wenn eine Ausnahme auftritt. Wie löst man im Kontextmanager eine Ausnahme aus, wenn der Heartbeat stoppt?

from contextlib import contextmanager
from threading import Thread, Event
from time import sleep


@contextmanager
def plc():
    stop_event = Event()

    try:
        # Send heartbeat every second
        hb_t = Thread(target=heartbeat_task,
                      args=(stop_event,),
                      daemon=True)
        hb_t.start()

        yield
    except Exception:
        raise
    finally:
        stop_event.set()
        hb_t.join()
        print("Heartbeat stopped")


def heartbeat_task(stop_event):

    value = False
    
    while not stop_event.is_set():

        value = not value

        print("Heartbeat: " + str(value))

        sleep(1)


def main():

    with plc():

        while True:

            print("Program running")

            sleep(5)

if __name__ == '__main__':
    main()
Nach dem Login kopieren

Es fällt mir schwer, Beispiele dafür zu finden.

Danke für deine Hilfe!


Richtige Antwort


aktualisiert

Ich habe den Code geändert, damit er besser mit dem von Ihnen geposteten Code übereinstimmt. Aber:

Der von Ihnen angegebene Code ist inkonsistent: heartbeat_task 传递了一个事件,如果设置该事件将导致函数返回。但只有当使用 with plc(): 创建的函数 main 中的上下文管理器退出时才会设置它,而这是永远不会的。如果您希望 heartbeat_task 抛出的任何异常将强制上下文管理器退出,然后在函数 plc 中捕获,那么调用 stop_event.set() 的意义何在?如果根据定义,我们仅在 heartbeat_task Sind Sie erst hierher gelangt, als er aufgrund einer Ausnahme nicht mehr existiert?

Entweder möchten Sie, dass heartbeat_task 无限期地运行,直到引发异常(在这种情况下,没有“停止”事件的意义),要么您希望能够在存在某些条件时停止 heartbeat_task,但没有这样做的代码。出于演示目的,我假设 main 将有权访问 stop_event 事件,并在某些情况下对其进行设置。否则,它会一直运行,直到检测到 heartbeat_task nie wieder ausgeführt wird, wahrscheinlich weil es eine Ausnahme ausgelöst hat (es führt eine Endlosschleife aus, wie kann es also möglicherweise beendet werden, wenn das Stoppereignis noch nicht festgelegt wurde?). Der Rest ist der Grund, warum Sie einen Kontextmanager verwenden müssen. Ich werde später eine Alternative vorschlagen.

Wenn Sie einen Multithread-Pool verwenden (wir benötigen nur einen Thread im Pool), wird es für den Hauptthread einfacher, die Ausnahme abzufangen, die von der an den Pool übermittelten Aufgabe ausgelöst wird: wenn die multiprocessing.pool.threadpool.apply_async 被调用时返回 multiprocessing.pool.asyncresult 实例,表示未来的完成。当在此实例上调用 get 方法时,您可以从辅助函数 (heartbeat_task) 获取返回值,或者重新引发辅助函数引发的任何异常。但是我们也可以使用 wait 方法来等待提交任务的完成或经过的时间。然后我们可以使用 ready-Methode testet, ob die Aufgabe übermittelt wurde nach 5 Sekunden Wartezeit ist es tatsächlich abgeschlossen (aufgrund einer Ausnahme oder Rückgabe). Wenn die Aufgabe noch läuft, können wir sie anweisen, anzuhalten. In dieser Demo erzwinge ich, dass die Aufgabe nach etwa 7 Sekunden eine Ausnahme auslöst:

from contextlib import contextmanager
from threading import event
from multiprocessing.pool import threadpool
from time import sleep


@contextmanager
def plc():
    stop_event = event()
    pool = threadpool(1)

    # send heartbeat every second
    async_result = pool.apply_async(heartbeat_task, args=(stop_event,))
    yield stop_event, async_result
    # we only return here if the task is no longer running
    try:
        # see if task threw an exception and if so, catch it:
        async_result.get()
    except exception as e:
        print("got exception:", e)
    finally:
        pool.close()
        pool.join()
        print("heartbeat stopped")


def heartbeat_task(stop_event):
    # for demo purposes, we will force an exception to occur
    # after approximately 7 seconds:
    value = false

    n = 0
    while not stop_event.is_set():
        value = not value
        print("heartbeat: " + str(value))
        sleep(1)
        n += 1
        if n == 7:
            raise exception('oops!')


def main():
    with plc() as tpl:
        stop_event, async_result = tpl
        # this function could forcibly cause the heartbeat_task
        # to complete by calling stop_event.set()

        # loop while the task is still running
        while not async_result.ready():
            """
            if some_condition:
                stop_event.set()
                break
            """
            print("program running")
            # sleep for 5 seconds or until heartbeat_task terminates:
            async_result.wait(5)

if __name__ == '__main__':
    main()
Nach dem Login kopieren

Drucken:

program running
heartbeat: true
heartbeat: false
heartbeat: true
heartbeat: false
heartbeat: true
program running
heartbeat: false
heartbeat: true
got exception: oops!
heartbeat stopped
Nach dem Login kopieren

Eine Alternative zur Verwendung von Kontextmanagern

from threading import Event
from multiprocessing.pool import ThreadPool
from time import sleep


def heartbeat_task(stop_event):
    value = False

    n = 0
    while not stop_event.is_set():
        value = not value
        print("Heartbeat: " + str(value))
        sleep(1)
        n += 1
        if n == 7:
            raise Exception('Oops!')

def main():
    stop_event = Event()
    pool = ThreadPool(1)
    async_result = pool.apply_async(heartbeat_task, args=(stop_event,))

    # Run as long as heartbeat_task is running:
    while not async_result.ready():
        """
        if some_condition:
            stop_event.set()
            break
        """
        print("Program running")
        # Sleep for 5 seconds or until heartbeat_task terminates:
        async_result.wait(5)

    # Any exception thrown in heartbeat_task will be rethrown and caught here:
    try:
        async_result.get()
    except Exception as e:
        print("Got exception:", e)
    finally:
        pool.close()
        pool.join()

if __name__ == '__main__':
    main()
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonKontextmanager und Daemon-Threads. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Wie löste ich das Problem der Berechtigungen beim Betrachten der Python -Version in Linux Terminal? Wie löste ich das Problem der Berechtigungen beim Betrachten der Python -Version in Linux Terminal? Apr 01, 2025 pm 05:09 PM

Lösung für Erlaubnisprobleme beim Betrachten der Python -Version in Linux Terminal Wenn Sie versuchen, die Python -Version in Linux Terminal anzuzeigen, geben Sie Python ein ...

Wie lehre ich innerhalb von 10 Stunden die Grundlagen für Computer-Anfänger-Programmierbasis in Projekt- und problemorientierten Methoden? Wie lehre ich innerhalb von 10 Stunden die Grundlagen für Computer-Anfänger-Programmierbasis in Projekt- und problemorientierten Methoden? Apr 02, 2025 am 07:18 AM

Wie lehre ich innerhalb von 10 Stunden die Grundlagen für Computer -Anfänger für Programmierungen? Wenn Sie nur 10 Stunden Zeit haben, um Computer -Anfänger zu unterrichten, was Sie mit Programmierkenntnissen unterrichten möchten, was würden Sie dann beibringen ...

Wie kann ich die gesamte Spalte eines Datenrahmens effizient in einen anderen Datenrahmen mit verschiedenen Strukturen in Python kopieren? Wie kann ich die gesamte Spalte eines Datenrahmens effizient in einen anderen Datenrahmen mit verschiedenen Strukturen in Python kopieren? Apr 01, 2025 pm 11:15 PM

Bei der Verwendung von Pythons Pandas -Bibliothek ist das Kopieren von ganzen Spalten zwischen zwei Datenrahmen mit unterschiedlichen Strukturen ein häufiges Problem. Angenommen, wir haben zwei Daten ...

Wie kann man vom Browser vermeiden, wenn man überall Fiddler für das Lesen des Menschen in der Mitte verwendet? Wie kann man vom Browser vermeiden, wenn man überall Fiddler für das Lesen des Menschen in der Mitte verwendet? Apr 02, 2025 am 07:15 AM

Wie kann man nicht erkannt werden, wenn Sie Fiddlereverywhere für Man-in-the-Middle-Lesungen verwenden, wenn Sie FiddLereverywhere verwenden ...

Wie hört Uvicorn kontinuierlich auf HTTP -Anfragen ohne Serving_forver () an? Wie hört Uvicorn kontinuierlich auf HTTP -Anfragen ohne Serving_forver () an? Apr 01, 2025 pm 10:51 PM

Wie hört Uvicorn kontinuierlich auf HTTP -Anfragen an? Uvicorn ist ein leichter Webserver, der auf ASGI basiert. Eine seiner Kernfunktionen ist es, auf HTTP -Anfragen zu hören und weiterzumachen ...

Wie erstelle ich dynamisch ein Objekt über eine Zeichenfolge und rufe seine Methoden in Python auf? Wie erstelle ich dynamisch ein Objekt über eine Zeichenfolge und rufe seine Methoden in Python auf? Apr 01, 2025 pm 11:18 PM

Wie erstellt in Python ein Objekt dynamisch über eine Zeichenfolge und ruft seine Methoden auf? Dies ist eine häufige Programmieranforderung, insbesondere wenn sie konfiguriert oder ausgeführt werden muss ...

Wie löste ich Berechtigungsprobleme bei der Verwendung von Python -Verssionsbefehl im Linux Terminal? Wie löste ich Berechtigungsprobleme bei der Verwendung von Python -Verssionsbefehl im Linux Terminal? Apr 02, 2025 am 06:36 AM

Verwenden Sie Python im Linux -Terminal ...

See all articles