2012-01-21 25 views
1

我有一个电子邮件帐户设置,每当它收到一封电子邮件时触发一个python脚本。该脚本经历了几个可能需要大约30秒的功能,并将条目写入MYSQL数据库。在python中创建一个处理队列

一切顺利,直到第一封电子邮件在第一封电子邮件发送后不到30秒内发送完毕。第二封电子邮件处理正确,但第一封电子邮件创建了一个损坏的数据库入口。

我期待保持电子邮件数据,

msg=email.message_from_file(sys.stdin) 
中如果脚本还没有处理完之前邮件队列

我正在使用python 2.5。 任何人都可以推荐一个可以实现这个目标的包/脚本吗?

+3

你了解了'Queue'包了吗?和'multiprocessing'软件包?和“芹菜”项目?阅读完所有这些内容后,你能否将这个问题改为更具体? –

+0

我会通读这些。感谢给我一个出发点。 – Ryan

+1

您是否编写了这个Python脚本,或者您只是使用它?为什么在世界上它会“腐化”任何东西?当您触发Python脚本时,它们处于单独的进程中,并且使用来自并发进程的数据库是典型做法,不应损坏数据。那么除了你描述的内容之外,你的代码还在做什么?您可能会更好地修复错误,然后创建一个队列来解决它们。 –

回答

2

我发现这是避免在以前的cronjob仍在运行时运行cronjob的简单方法。

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

这将引发一个IOError,然后通过让进程自行终止来处理。

请参阅http://docs.python.org/library/fcntl.html#fcntl.lockf了解更多信息。

无论如何,你可以很容易地使用相同的想法,一次只允许一个作业运行,这实际上与队列不一样(因为任何进程在等待都可能获得锁),但它实现了什么你要。

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

虽然芹菜是一个非常好的软件,在这种情况下使用它类似于用大锤驾驶钉子。在概念层面上,寻找一个工作队列(这是芹菜提供的),但您用来触发脚本的电子邮件收件箱是有能力的工作队列。

更直接的解决方案是让Python工作者脚本自己轮询邮件服务器(例如使用内置的poplib)每隔几秒检索一次新邮件,然后一次处理所有新邮件。这将序列化脚本正在执行的工作,从而防止一次运行两个副本。

例如,你想包你现有的脚本这样的功能(从上面链接的文档):

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) 

编辑:语法