2016-09-02 3 views
1

Windows에서 Python 3.5.2를 사용하고 있습니다.파이썬에서 자식 스레드 내에서 부모 스레드를 죽일 수 있습니까?

파이썬 스크립트를 실행하고 싶지만 N 초 이상 걸리지 않도록하십시오. 일 경우 N 초 이상 걸릴 경우 예외가 발생하고 프로그램을 종료해야합니다. 처음에는 예외를 던지기 전에 N 초를 기다리는 스레드를 처음 시작할 수 있다고 생각했지만,이 작업은 상위 스레드가 아니라 타이머 스레드에 예외를 던지기 만합니다.

import threading 
import time 

def may_take_a_long_time(name, wait_time): 
    print("{} started...".format(name)) 
    time.sleep(wait_time) 
    print("{} finished!.".format(name)) 

def kill(): 
    time.sleep(3) 
    raise TimeoutError("No more time!") 

kill_thread = threading.Thread(target=kill) 
kill_thread.start() 

may_take_a_long_time("A", 2) 
may_take_a_long_time("B", 2) 
may_take_a_long_time("C", 2) 
may_take_a_long_time("D", 2) 

이 출력 : 예를 들어

A started... 
A finished!. 
B started... 
Exception in thread Thread-1: 
Traceback (most recent call last): 
    File "C:\Program Files\Python35\lib\threading.py", line 914, in _bootstrap_inner 
    self.run() 
    File "C:\Program Files\Python35\lib\threading.py", line 862, in run 
    self._target(*self._args, **self._kwargs) 
    File "timeout.py", line 11, in kill 
    raise TimeoutError("No more time!") 
    TimeoutError: No more time! 

B finished!. 
C started... 
C finished!. 
D started... 
D finished!. 

이 가능한 원격 짝수? 나는 이런 식으로 뭔가를 할 수 실현 :

import threading 
import time 

def may_take_a_long_time(name, wait_time, thread): 
    if not thread.is_alive(): 
     return 
    print("{} started...".format(name)) 
    time.sleep(wait_time) 
    print("{} finished!.".format(name)) 

def kill(): 
    time.sleep(3) 
    raise TimeoutError("No more time!") 

kill_thread = threading.Thread(target=kill) 
kill_thread.start() 

may_take_a_long_time("A", 2, kill_thread) 
may_take_a_long_time("B", 2, kill_thread) 
may_take_a_long_time("C", 2, kill_thread) 
may_take_a_long_time("D", 2, kill_thread) 

그러나이 방법은 예를 들어, may_take_a_long_time("B", 60, kill_thread)가 호출, 경우에 실패합니다.

그래서 내 TL; DR 질문은, 메인 스레드 자체에 시간 제한을 두는 가장 좋은 방법은 무엇입니까?

+0

당신은 모든 파이썬 스레드를 _kill_ 수 없습니다. 이를위한 API가 없습니다. 그리고 코드에서 수행중인 작업은 새로운 thread_ 내에서 예외를 발생시키는 것일 뿐이므로 메인 스레드에는 영향을 미치지 않습니다. – ForceBru

+0

시간 제한의 목적은 무엇입니까? 특정 시간 이상 동안 어떤 일이 일어날 때까지 기다리지 않으려면 대기를 그만 두십시오. –

+0

@ForceBru 나는 ​​그것이 주된 것에 영향을 미치지 않는다는 것을 안다. 그것은 나의 문제이다. 이것은 나의 초기 순진 구현이었다. 일련의 함수 ('may_take_a_long_time')가 ** N ** 초 이상 걸리지 않도록하는 방법을 찾으려고합니다. – DJMcMayhem

답변

3

당신은 (이 모듈은 파이썬 2.7에서 thread라고합니다) _thread.interrupt_main를 사용할 수 있습니다

import time, threading, _thread 

def long_running(): 
    while True: 
     print('Hello') 

def stopper(sec): 
    time.sleep(sec) 
    print('Exiting...') 
    _thread.interrupt_main() 

threading.Thread(target = stopper, args = (2,)).start() 

long_running() 
+0

안녕하세요! 그게 바로 제가 찾고 있던 것입니다 (그리고 너무 빠릅니다!). 어떤 예외가 발생했는지를 변경하는 것이 가능한지 아십니까? 'KeyboardInterrupt'는 내가하는 일에별로 관련이없는 것처럼 보입니다. – DJMcMayhem

+0

@DJMcMayhem, 문서에 의하면 :이 함수는'KeyboardInterrupt'를 던집니다. 사실, 전역 변수를 사용하여 몇 가지 속임수를 사용하면 예외가 '스토퍼'로 발생하고이 사례를 다르게 처리 함을 나타낼 수 있습니다. 그러나 주 스레드에서 예외를 catch하면 장시간 실행되는 함수가 종료되고 결과가 손실되므로 해당 함수 자체에서 _ 처리 할 수 ​​있습니다. – ForceBru

2

상위 스레드가 루트 스레드 인 경우 os._exit(0)을 시도 할 수 있습니다.

import os 
import threading 
import time 

def may_take_a_long_time(name, wait_time): 
    print("{} started...".format(name)) 
    time.sleep(wait_time) 
    print("{} finished!.".format(name)) 

def kill(): 
    time.sleep(3) 
    os._exit(0) 

kill_thread = threading.Thread(target=kill) 
kill_thread.start() 

may_take_a_long_time("A", 2) 
may_take_a_long_time("B", 2) 
may_take_a_long_time("C", 2) 
may_take_a_long_time("D", 2) 
+1

불행히도, 그것은 작동하지 않습니다. 나는'sys.exit()'가 부모 스레드의 행동을 바꾸지 않고서 어떤 스레드가 호출되었는지에 제한되어 있다고 생각한다. – DJMcMayhem

+0

'os._exit (n)'이 맞습니다. – rbanffy

+0

그게 더 잘 작동하지만, 실제로는 예외를 일으키지 않거나 오류를 던지지 않기 때문에 아마 사용하지 않을 것입니다. – DJMcMayhem

관련 문제