Форум сайта python.su
173
CommonUserОпишите, что хотите сделать. Думаю, все-таки нужна очередь.
Скажите пожалуйста, как создать новый поток и использовать его несколько раз, то есть запускать, а не создавать снова. Python 2.7
Офлайн
0
Да про очереди и задачи, я понял и разобрался. У меня теперь вопрос в другом:
from datetime import datetime import sys import threading import time def timed_run(func, args=(), kwargs={}, timeout=None): class TimedThread(threading.Thread): """An abortable thread, by merly raising an exception inside its context. """ def __init__(self): super(TimedThread, self).__init__() self.exc_info = (None, None, None) def run(self): self.started_at = datetime.now() try: self.result = func(*args, **kwargs) except: # save the exception as an object attribute self.exc_info = sys.exc_info() self.result = None self.ended_at = datetime.now() def abort(self): self.ended_at = datetime.now() raise RuntimeError("Thread aborted as requested.") t = TimedThread() t.start() t.join(timeout) if t.exc_info[0] is not None: # if there were any exceptions t, v, tb = t.exc_info raise t, v, tb # Raise the exception/traceback inside the caller if t.is_alive(): t.abort() diff = t.ended_at - t.started_at raise RuntimeError("%(f)s timed out after %(d)r seconds" % {'f': func, 'd': diff.seconds}) return t.result def func(): # Unstoppable func while True: print "I am an unstoppable" time.sleep(5) return "done" if __name__ == '__main__': print timed_run(func=func,timeout=10)
Отредактировано CommonUser (Март 5, 2013 10:56:01)
Офлайн
173
Вот описание почему
http://eli.thegreenplace.net/2011/08/22/how-not-to-set-a-timeout-on-a-computation-in-python/
там же и что делать.
Вкратце: для nix - сигналы, для win - процессы, а еще лучше контролировать завершение работы внутри потока (функции).
Есть еще одно “полурешение”:
from threading import Timer import thread import time class TimeoutError(Exception): """Function timed out""" def timed_run(func, args=(), kwargs={}, timeout=None): start = time.time() try: Timer(timeout, thread.interrupt_main).start() return func(*args, **kwargs) except KeyboardInterrupt: raise TimeoutError("%s timed out (%.2f seconds)" % (func, time.time() - start)) def func(): # Unstoppable func while True: print "I am an unstoppable" time.sleep(5) return "done" if __name__ == '__main__': print timed_run(func=func,timeout=1.0)
Офлайн
0
Автор в блоге пишет.
So even more sophisticated “solutions” propose to ditch the Python-level-API and just brutally kill a thread with pthread_kill (on Unix) or TerminateThread (on Windows). This is a very bad idea.
Придётся на multiprocessing переходить или на библиотеку гринлетов
Что-то вроде:
from multiprocessing.process import Process import time def func(): while True: print "I am an unstoppable" time.sleep(1) result = None timeout = 15 p = Process(target=func) p.start() # waiting for timeout p.join(timeout) print "timeout has elapsed or process has finished" if p.is_alive(): p.terminate() print "terminating the process" time.sleep(10) print "p.is_alive = %r" % p.is_alive()
import multiprocessing import time resultq = multiprocessing.Queue(1) def func1(): while True: print "I am an unstoppable" time.sleep(1) #time.sleep(5) return True def func2(): time.sleep(5) return "Result of func2" def _func(func=None, func_args=()): result = func(*func_args) resultq.put(result) def timedoutRun(func=None, f_args=()): timeout = 10 result = None p = multiprocessing.Process(target=_func, args=(func,)+f_args) p.start() # waiting for timeout p.join(timeout) print "timeout has elapsed or process has finished" if resultq.empty(): print "We do not have a result of func because of the func gets stuck" else: print "process has competed" result = resultq.get() print "result is %r" % result if p.is_alive(): p.terminate() print "terminating the process" time.sleep(10) print "p.is_alive = %r" % p.is_alive() return result if __name__ == '__main__': print "start" print timedoutRun(func1) print timedoutRun(func2) print "end"
Отредактировано CommonUser (Март 6, 2013 08:54:56)
Офлайн
> Есть Queue, внутри них используются локи. Код да, странный, я не обращал внимания на параметры).
> Видимо тут автор просмотрел это, а так параметры всё равно глобально передаются, то всё так и осталось работать.
Fixed https://bitbucket.org/lorien/grab/commits/c448bd767c974b501d6878312ebd6da073014bd1
Офлайн