主程序退出时终止线程

2024-04-25 23:43:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试开始使用Python中的多线程。我有多个线程获取锁,执行操作,释放锁,并将结果输出到csv文件。如果主线程结束,则应终止线程(例如,通过按Ctrl+C)。这是怎么做到的?你知道吗

我认为创建线程守护进程应该可以完成这项工作,因为“当只剩下守护进程线程时,整个Python程序就会退出”(官方Python文档)。这是不够的。根据python: how to terminate a thread when main program ends,我尝试捕捉键盘中断,然后手动终止线程。此外,这是不工作的,似乎是键盘中断捕捉不正确。你知道吗

这让我想到,Python中的多线程有些地方我误解了。。。查找附件我的代码:

import random
import csv
import sys
from datetime import datetime
import threading

lock = threading.Lock()

def observer(obs):
    print("In " + str(obs))
    sys.stdout.flush()        

    with open("data/test_" + str(obs) + ".csv", 'a', newline='') as csvfile:
        while True:
            datenow = datetime.today()        
            lock.acquire()
            print(str(obs) + "acquired")
            sum = 0
            for i in range(10000):
                sum = sum + random.random()
            print(str(obs) + "released")
            sys.stdout.flush()
            lock.release()

            writer = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_ALL)
            writer.writerow([datenow.isoformat(), sum/10000])
            #print(str(obs) + ": " + datenow.isoformat() + " " + str(sum/1000))
            sys.stdout.flush()

if __name__ == "__main__":
    observe = [1, 2, 3, 4]

    processes = []
    for obs in observe:
        process = threading.Thread(target=observer, args=(obs,), daemon=True)
        processes.append(process)

    print("Start processes")
    for p in processes:
        p.start()

    print("Started")
    try:
        for p in processes:
            p.join()
    except KeyboardInterrupt:
        for p in processes:
            p.terminate()
        print("Keyboard interrupt")

    print("Finished")

谢谢!你知道吗


Tags: csvinimportlockfordatetimesysrandom
1条回答
网友
1楼 · 发布于 2024-04-25 23:43:39

这是错误的

try:
    for p in processes:
        p.join()
except KeyboardInterrupt:
    for p in processes:
        p.terminate()
    print("Keyboard interrupt")

您的线程永远不会退出while True:循环,因此您将永远加入它们。但这不是重点。你知道吗

如果Ctrl-C(又名KeyboardInterrupt)没有被抓住,我的最佳选择是:

  • 您正在Windows下运行Python
  • 运行脚本的shell会操纵进程,而实际上您永远看不到Ctrl-C,因为您的程序正在突然终止。你知道吗

你的问题是:

  • 你的程序实际上并不知道它已经终止,这就是线程挂起的原因。你知道吗

如果上面的假设是正确的,请尝试以下代码(从Python - Windows - Exiting Child Process when "unrelated" parent dies/crashes

import sys

def win_wait_for_parent(raise_exceptions=False):
    if not sys.platform == 'win32':
        return True

    # When started under cygwin, the parent process will die leaving a child
    # hanging around. The process has to be waited upon
    import ctypes
    from ctypes.wintypes import DWORD, BOOL, HANDLE
    import os
    import threading

    INFINITE = -1
    SYNCHRONIZE = 0x00100000

    kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

    kernel32.OpenProcess.argtypes = (DWORD, BOOL, DWORD)
    kernel32.OpenProcess.restype = HANDLE

    kernel32.WaitForSingleObject.argtypes = (HANDLE, DWORD)
    kernel32.WaitForSingleObject.restype = DWORD

    phandle = kernel32.OpenProcess(SYNCHRONIZE, 0, os.getppid())

    def check_parent():
        # Get a token with right access to parent and wait for it to be
        # signaled (die). Exit ourselves then
            kernel32.WaitForSingleObject(phandle, INFINITE)
            os._exit(0)

    if not phandle:
        if raise_exceptions:
            raise ctypes.WinError(ctypes.get_last_error())

        return False

相关问题 更多 >