更新:正如 Fooz 先生所指出的,包装器的功能版本有一个错误,所以我恢复到原来的类实现。我已经把代码放在了 GitHub 上:
https://github.com/nofatclips/timeout/commits/master
有两个提交,一个工作(使用“导入”解决方法)第二个被破坏。
问题的根源似乎是pickle#dumps
函数,它只是在函数上调用时吐出一个标识符。当我调用Process
时,该标识符指向函数的修饰版本,而不是原始版本。
原始信息:
我试图编写一个函数装饰器来将一个长任务包装在一个进程中,如果超时到期,该进程将被终止。我想出了这个(工作但不优雅)版本:
from multiprocessing import Process
from threading import Timer
from functools import partial
from sys import stdout
def safeExecution(function, timeout):
thread = None
def _break():
#stdout.flush()
#print (thread)
thread.terminate()
def start(*kw):
timer = Timer(timeout, _break)
timer.start()
thread = Process(target=function, args=kw)
ret = thread.start() # TODO: capture return value
thread.join()
timer.cancel()
return ret
return start
def settimeout(timeout):
return partial(safeExecution, timeout=timeout)
#@settimeout(1)
def calculatePrimes(maxPrimes):
primes = []
for i in range(2, maxPrimes):
prime = True
for prime in primes:
if (i % prime == 0):
prime = False
break
if (prime):
primes.append(i)
print ("Found prime: %s" % i)
if __name__ == '__main__':
print (calculatePrimes)
a = settimeout(1)
calculatePrime = a(calculatePrimes)
calculatePrime(24000)
如您所见,我注释掉了装饰器并将修改后的 calculatePrimes 版本分配给了 calculatePrime。如果我尝试将其重新分配给同一个变量,则在尝试调用修饰版本时会收到“无法腌制:属性查找 builtins.function 失败”错误。
有人知道引擎盖下发生了什么吗?当我将装饰版本分配给引用它的标识符时,原始函数是否会变成不同的东西?
更新:为了重现错误,我只是将主要部分更改为
if __name__ == '__main__':
print (calculatePrimes)
a = settimeout(1)
calculatePrimes = a(calculatePrimes)
calculatePrimes(24000)
#sleep(2)
产生:
Traceback (most recent call last): File "c:\Users\mm\Desktop\ING.SW\python\thread2.py", line 49, in <module> calculatePrimes(24000) File "c:\Users\mm\Desktop\ING.SW\python\thread2.py", line 19, in start ret = thread.start() File "C:\Python33\lib\multiprocessing\process.py", line 111, in start self._popen = Popen(self) File "C:\Python33\lib\multiprocessing\forking.py", line 241, in __init__ dump(process_obj, to_child, HIGHEST_PROTOCOL) File "C:\Python33\lib\multiprocessing\forking.py", line 160, in dump ForkingPickler(file, protocol).dump(obj) _pickle.PicklingError: Can't pickle <class 'function'>: attribute lookup builtin s.function failed Traceback (most recent call last): File "<string>", line 1, in <module> File "C:\Python33\lib\multiprocessing\forking.py", line 344, in main self = load(from_parent) EOFError
PS我还写了一个安全执行的类版本,它具有完全相同的行为。