我设置了一个电子邮件帐户,只要收到电子邮件,就会触发python脚本。该脚本经历了几个函数,这些函数可能需要大约30秒并将条目写入MYSQL数据库。
一切顺利进行,直到第一封电子邮件在第一封电子邮件发送后不到30秒内发送。第二封电子邮件处理正确,但第一封电子邮件会在数据库中创建损坏的条目。
我希望保留电子邮件数据,
msg=email.message_from_file(sys.stdin)
如果脚本尚未处理完之前的电子邮件,则在队列中。
我正在使用python 2.5。 任何人都可以推荐一个可以实现此目的的包/脚本吗?
答案 0 :(得分:2)
我非常肯定会完全满足您的需求。
答案 1 :(得分: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 :(得分:2)
虽然Celery是一款非常精美的软件,但在这种情况下使用它类似于用大锤驱动钉子。在概念层面,您 正在寻找一个作业队列(这是芹菜提供的),但您用来触发脚本的电子邮件收件箱也一个能力作业队列。
更直接的解决方案是让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)
编辑:语法