存储代码以备后用的最佳方法(python)
我有一些任务存储在数据库里,准备以后执行。比如说,我可以设置一个发送邮件的任务。然后通过定时任务(cron)来执行这个任务。我在寻找一种最佳的方法,把代码存储在数据库中,以便以后执行。比如说,我可以把它存成一段原始的Python代码字符串,然后用eval来执行,但我还需要在这里存储相对导入。
比如说,要发送邮件,我需要把字符串设置成这样:
s = "from django.core.mail import send_mail\n send_mail('subj', 'body', 'email@box.ru',['email1@box.ru'], fail_silently=False)"
然后再用eval执行……有没有更好的方法或者更合适的模式来处理这种任务呢?
5 个回答
可以使用 celery
来解决这个问题。这是最好的方法。
我完全不会使用这个方法。我会为每个任务(比如发送邮件、删除文件等)创建一个不同的处理器。这样存储代码的方式有点像是临时拼凑,不太正规。
补充说明
举个例子,可以为处理器创建你自己的格式。比如,每一行就是一个处理器,格式如下:
handlername;arg1;arg2;arg3;arg4
接下来,你可以用Python来读取这些行并解析它们。比如,这一行存储的内容是:
sendmail;nightcracker@nclabs.org;subject;body
然后可以这样解析:
for line in database:
handler, *args = line.split(";")
if handler == "sendmail":
recipient, subject, body, = args[:3]
# do stuff
elif handler == "delfile":
#etc
你现在做的事情其实不太好,主要是因为你允许代码执行的内容变化太大。代码字符串可以做的事情是非常广泛的,而我猜你想要存储的任务其实就几种。
所以,先弄清楚这些任务中有哪些变量(这里的变量不是编程里的意思,而是指那些会变化的东西),然后只存储这些变量。你可以把它们存成一个包含函数参数的元组和一个包含关键字参数的字典,这些参数是要应用到一个已知的函数上的。
如果想要更高级一点,你可以创建一个包含多个函数的容器对象,然后存储要调用的函数名和它的参数。这个容器可以简单到像一个模块,你可以在里面导入像Django的 send_mail
这样的函数,就像你例子里那样。
然后你可以这样存储你的示例调用:
func = 'send_mail'
args = ('subj', 'body', 'email@box.ru', ['email1@box.ru'])
kwargs = {'fail_silently': False}
my_call = cPickle.dumps((func, args, kwargs))
并且可以这样使用它:
func, args, kwargs = cPickle.loads(my_call)
getattr(my_module, func)(*args, **kwargs)