我有一个python脚本,它运行一个特定的脚本很多次(对于蒙特卡罗的目的)和我编写脚本的方式是,我排队脚本所需的次数它应该运行然后我产生线程和每个线程在完成后一次又一次地运行脚本。
一旦特定线程中的脚本完成,输出就会通过访问锁定写入文件(因此我猜测只有一个线程在给定时间访问锁定)。一旦一个线程释放了锁,下一个线程就会访问它并将其输出添加到先前写入的文件中并重写它。
当迭代次数很小,如10或20时,我没有遇到问题,但当它的大小如50或150时,python返回一个KeyError:51告诉我元素不存在,它指出的错误是在锁定中让我感到困惑,因为只有一个线程应该立即访问锁定,我不希望出现错误。
这是我使用的课程:
class errorclass(threading.Thread):
def __init__(self, queue):
self.__queue=queue
threading.Thread.__init__(self)
def run(self):
while 1:
item = self.__queue.get()
if item is None: break
result = myfunction()
lock = threading.RLock()
lock.acquire()
ADD entries from current thread to entries in file and
REWRITE FILE
lock.release()
queue = Queue.Queue()
for i in range(threads):
errorclass(queue).start()
for i in range(desired iterations):
queue.put(i)
for i in range(threads):
queue.put(None)
Python返回KeyError:51,在锁定访问后的添加/写入文件操作期间进行大量所需的迭代,我想知道这是否是使用锁的正确方法,因为每个线程都有一个锁定操作而不是每个线程访问共享锁?什么方法可以纠正这个问题?
答案 0 :(得分:1)
您现在拥有的是每个线程的run
方法中每个迭代的新锁。实际上,根本没有锁定。如果要保护对文件的写入,则需要确保访问同一文件的所有线程使用相同的锁定对象。最简单的方法是在全局级别创建它:
lock = threading.RLock()
class errorclass(...):
...
def run(self)
... # get items and process
with lock:
ADD entries from current thread to entries in file and REWRITE FILE
您需要使用from __future__ import with_statement
在Python 2.5中使用with
语句,但它确保您永远不会忘记解锁,即使发生错误也不会。 (如果你需要Python 2.4及更早版本的兼容性,你将不得不使用try / finally。)
答案 1 :(得分:0)
创建锁并将其传递给errorclass.__init__
,以便他们共享一个实例。否则,每个线程都会锁定自己重新进入他们自己的关键部分,这完全是一个无操作。