ロングアイズのポストを前にして謝っています。うまくいけば、それは解決のための十分な文脈を与えるでしょう。私は古いclassmethod
の任意の数を取り、マルチスレッドのキューにそれらを固執するユーティリティ関数を作成しようとしました:Pythonスレッディング:何が欠けていますか? (task_done()があまりにも多く呼ばれました)
class QueuedCall(threading.Thread):
def __init__(self, name, queue, fn, args, cb):
threading.Thread.__init__(self)
self.name = name
self._cb = cb
self._fn = fn
self._queue = queue
self._args = args
self.daemon = True
self.start()
def run(self):
r = self._fn(*self._args) if self._args is not None \
else self._fn()
if self._cb is not None:
self._cb(self.name, r)
self._queue.task_done()
はここ
私の呼び出し元のコードが(クラス内)のようになりますdata = {}
def __op_complete(name, r):
data[name] = r
q = Queue.Queue()
socket.setdefaulttimeout(5)
q.put(QueuedCall('twitter', q, Twitter.get_status, [5,], __op_complete))
q.put(QueuedCall('so_answers', q, StackExchange.get_answers,
['api.stackoverflow.com', 534476, 5], __op_complete))
q.put(QueuedCall('so_user', q, StackExchange.get_user_info,
['api.stackoverflow.com', 534476], __op_complete))
q.put(QueuedCall('p_answers', q, StackExchange.get_answers,
['api.programmers.stackexchange.com', 23901, 5], __op_complete))
q.put(QueuedCall('p_user', q, StackExchange.get_user_info,
['api.programmers.stackexchange.com', 23901], __op_complete))
q.put(QueuedCall('fb_image', q, Facebook.get_latest_picture, None, __op_complete))
q.join()
return data
私はここに実行している問題は、新鮮なサーバの再起動にごとタイムで働くように見えるということですが、エラーで、すべての第二または第三の要求を失敗:
ValueError: task_done() called too many times
このエラーは2番目または3番目の要求ごとにランダムなスレッドになりますので、正確にの問題を解決することはむしろ困難です。
誰でも意見や提案がありますか?
ありがとうございました。
編集:私はこの(迅速かつ汚いのではなく、ロギング)をデバッグするための努力でprint
秒を追加した
。 run
の1行目の印刷ステートメント(print 'running thread: %s' % self.name
)とtask_done()
(print 'thread done: %s' % self.name
)を呼び出す前のもう1つの印刷ステートメント
成功した要求の出力:
running thread: twitter
running thread: so_answers
running thread: so_user
running thread: p_answers
thread done: twitter
thread done: so_user
running thread: p_user
thread done: so_answers
running thread: fb_image
thread done: p_answers
thread done: p_user
thread done: fb_image
失敗した要求の出力:
running thread: twitter
running thread: so_answers
thread done: twitter
thread done: so_answers
running thread: so_user
thread done: so_user
running thread: p_answers
thread done: p_answers
Exception in thread p_answers:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/home/demian/src/www/projects/demianbrecht/demianbrecht/demianbrecht/helpers.py", line 37, in run
self._queue.task_done()
File "/usr/lib/python2.7/Queue.py", line 64, in task_done
raise ValueError('task_done() called too many times')
ValueError: task_done() called too many times
running thread: p_user
thread done: p_user
running thread: fb_image
thread done: fb_image
スレッドが 'task_done'呼び出しの前に診断を出力するようにしてデバッグしようとしましたか? –
@カール:はい、編集をご覧ください。 –
もう少し詳しく:スレッドを0.1秒間スリープ状態にしても、エラーを再現することはできません。 Grr。明らかに、私はまだ問題の根本を見つけたいと思っています。 –