Python中的可中断线程连接 [英] Interruptible thread join in Python

查看:49
本文介绍了Python中的可中断线程连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么方法可以等待线程终止,但是仍然可以拦截信号?

请考虑以下 C 程序:

#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>

void* server_thread(void* dummy) {
    sleep(10);
    printf("Served\n");
    return NULL;
}

void* kill_thread(void* dummy) {
    sleep(1); // Let the main thread join
    printf("Killing\n");
    kill(getpid(), SIGUSR1);
    return NULL;
}

void handler(int signum) {
    printf("Handling %d\n", signum);
    exit(42);
}

int main() {
    pthread_t servth;
    pthread_t killth;

    signal(SIGUSR1, handler);

    pthread_create(&servth, NULL, server_thread, NULL);
    pthread_create(&killth, NULL, kill_thread, NULL);

    pthread_join(servth, NULL);

    printf("Main thread finished\n");
    return 0;
}

一秒钟后结束并打印:

Killing
Handling 10

相比之下,这是我尝试用 Python 编写的代码:

In contrast, here's my attempt to write it in Python:

#!/usr/bin/env python
import signal, time, threading, os, sys

def handler(signum, frame):
    print("Handling " + str(signum) + ", frame:" + str(frame))
    exit(42)
signal.signal(signal.SIGUSR1, handler)

def server_thread():
    time.sleep(10)
    print("Served")
servth = threading.Thread(target=server_thread)
servth.start()

def kill_thread():
    time.sleep(1) # Let the main thread join
    print("Killing")
    os.kill(os.getpid(), signal.SIGUSR1)
killth = threading.Thread(target=kill_thread)
killth.start()

servth.join()

print("Main thread finished")

它打印:

Killing
Served
Handling 10, frame:<frame object at 0x12649c0>

如何使它的行为类似于C版本?

推荐答案

Jarret Hardie已经 Guido van Rossum ,到目前为止,没有更好的方法了:如文档所述,join(None)块(这意味着没有信号).另一种选择-调用超时很大(join(2**31)左右)并检查isAlive看起来不错.但是,Python处理计时器的方式是灾难性的,如使用servth.join(100)而不是servth.join()来运行python测试程序时所见:

Jarret Hardie already mentioned it: According to Guido van Rossum, there's no better way as of now: As stated in the documentation, join(None) blocks (and that means no signals). The alternative - calling with a huge timeout (join(2**31) or so) and checking isAlive looks great. However, the way Python handles timers is disastrous, as seen when running the python test program with servth.join(100) instead of servth.join():

select(0, NULL, NULL, NULL, {0, 1000})  = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 2000})  = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 4000})  = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 8000})  = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 16000}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 32000}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 50000}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 50000}) = 0 (Timeout)
select(0, NULL, NULL, NULL, {0, 50000}) = 0 (Timeout)
--- Skipped 15 equal lines ---
select(0, NULL, NULL, NULL, {0, 50000}Killing

即,Python每隔50毫秒唤醒一次,从而导致一个应用程序使CPU保持睡眠状态.

I.e., Python wakes up every 50 ms, leading to a single application keeping the CPU from sleeping.

这篇关于Python中的可中断线程连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆