2012-01-21 8 views
1

電子メールを受信するたびにpythonスクリプトをトリガーする電子メールアカウントを設定しました。スクリプトは、約30秒かかることがあり、MYSQLデータベースにエントリを書き込むいくつかの機能を実行します。Pythonで処理キューを作成する

2回目のメールが最初のメールから30秒以内に送信されるまで、すべてがスムーズに実行されます。 2番目の電子メールは正しく処理されますが、最初の電子メールはデータベースに破損したエントリを作成します。

私は電子メールのデータを保持しているよ、スクリプトは前のメール処理を完了していない場合は、キュー内の

msg=email.message_from_file(sys.stdin) 

私はPython 2.5を使用しています。 誰でもこれを達成するパッケージ/スクリプトをお勧めできますか?

+3

は、あなたがまだ 'Queue'パッケージについて読みました文法?そして 'マルチプロセッシング'パッケージ?そしてセロリプロジェクト?それらのすべてを読んだ後で、より具体的に質問を言い換えることができますか? –

+0

私はそれらを読むでしょう。私に出発点を与えてくれてありがとう。 – Ryan

+1

このPythonスクリプトを書いたのですか、それとも使っていますか?なぜ世界でそれは何か「腐敗する」でしょうか?Pythonスクリプトをトリガーするときは、別々のプロセスにあり、並行プロセスのDBを使用するのが一般的な方法です。データを破損しないようにする必要があります。あなたの記述以外にあなたのコードは何ですか?バグを修正してから回避する方が良いかもしれません。 –

答えて

2

これは、以前のcronジョブがまだ実行されている間にcronジョブを実行しないようにする簡単な方法です。

fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) 

これは、プロセスが自分自身をkillすることによって処理するIOErrorを発生させます。

詳細はhttp://docs.python.org/library/fcntl.html#fcntl.lockfを参照してください。

とにかく同じアイデアを使用すれば、一度に1つのジョブを実行することができます。待機中のプロセスはロックを取得する可能性があるため、実際にはキューと同じではありませんが、あなたは欲しい。

import fcntl 
import time 
fd = open('lock_file', 'w') 
fcntl.lockf(fd, fcntl.LOCK_EX) 
# optionally write pid to another file so you have an indicator 
# of the currently running process 
print 'Hello' 
time.sleep(1) 

また、http://docs.python.org/dev/library/multiprocessing.html#exchanging-objects-between-processesを使用して、まさにあなたが望むことを行うこともできます。

2

私は正確にあなたのニーズを満たすことかなり確信しているhttp://celeryproject.org/

になります。

2

セロリは非常に細かいソフトウェアですが、このシナリオではセレンはハンマーで釘打ちするのに似ています。概念レベルでは、(ジョブ・キューはセロリが提供するものです)ですが、スクリプトをトリガーするために使用している電子メール・インボックスはでも可能なジョブ・キューです。

もっと直接的な解決策は、Pythonワーカースクリプトが(例えば、poplibに組み込まれている)メールサーバーをポーリングすることです。数秒ごとに新しいメールをすべて取得し、新しいメールを1つずつ処理します。これにより、スクリプトが実行している作業がシリアル化され、2つのコピーが一度に実行されなくなります。

たとえば、あなたは、(上記のリンクのドキュメントからの)このような関数では、既存のスクリプトをラップします:

import getpass, poplib 
from time import sleep 

M = poplib.POP3('localhost') 
M.user(getpass.getuser()) 
M.pass_(getpass.getpass()) 
while True: 
    numMessages = len(M.list()[1]) 
    for i in range(numMessages): 
     email = '\n'.join(M.retr(i+1)[1]) 
     # This is what your script normally does: 
     do_work_for_message(email) 
    sleep(5) 

編集:

関連する問題