存储代码以供以后执行的最佳方法(python)

时间:2011-01-10 22:54:31

标签: python serialization queue task

我有一些任务存储在db中以便以后执行。例如,我可以修复发送电子邮件的任务。并通过cron exec任务(发送它)。我搜索在db中存储代码以便以后执行的最佳方法。对于ex存储它的原始字符串的python代码,而不是eval,但我也必须在这里存储相对导入..

例如发送电子邮件我必须修复这样的字符串:

s =“来自django.core.mail import send_mail \ n send_mail('subj','body','email @ box.ru',['email1 @ box.ru'],fail_silently = False)“

以及之后的评估..任何想法都是最好的方式或更好的模式来完成这种任务?

5 个答案:

答案 0 :(得分:5)

你正在做的是一个坏主意,主要是因为你允许在执行什么代码方面有太多的变化。代码字符串可以任何,我猜你只想存储几种任务以便以后执行。

因此,弄清楚这些任务中的变量是什么(非编程意义上的变量:变化的东西),并且只存储这些变量,可能作为函数参数的元组和要应用的关键字参数的字典已知的功能。

更加花哨的是,你可以拥有某种带有大量函数的容器对象,并存储要调用的函数的名称及其参数。该容器可以像您在其中导入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)

答案 1 :(得分:2)

我根本不会使用这个解决方案。我会为每个任务创建一个不同的处理程序(发送邮件,删除文件等)。以这种方式存储代码是一种破坏。

修改

一个例子是为处理程序创建自己的格式。例如,以这种格式的每一行处理程序:

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

答案 2 :(得分:2)

使用celery。这是最好的方法。

http://celeryproject.org/

答案 3 :(得分:1)

我会存储逻辑命令,并用

之类的命令执行它们
def run_command(cmd):
    fields = map(unescape, cmd.split(";"))
    handlers[fields[0]](fields[1:])

...

@handler("mail")
def mail_handler(address, template):
    import whatever
    ...
    send_mail(address, get_template(template) % user_info, ...)

通过这种方式,您可以灵活地添加处理程序,而无需触及调度程序中的任何代码,但您不会在数据库中编写代码详细信息,这会使检查/统计信息变得更难,或只是热修复作业尚未开始。

答案 4 :(得分:0)

要直接回答您的问题,eval实际上仅用于评估将产生结果的代码。例如:

>>> eval('1 + 1')
2

但是如果你只是想执行代码,可能是几行代码,你需要exec(),它默认在调用者的命名空间内执行:

>>> exec("x = 5 + 5")
>>> print x
10

请注意,只应将受信任的代码传递给exec或eval。另请参见execfile以执行文件。

说了这么多,我同意其他海报,你应该找到一种方法来解决问题,而不是存储任意代码。例如,你可以这样做:

def myMailCommand(...):
    ...

def myOtherCommand(...):
    ...

available_commands = {'mail': myMailCommand,
                      'other': myOtherCommand}

to_execute = [('mail', (arg1, arg2, arg3)),
              ('other', (arg1, arg2))]

for cmd, args in to_execute:
    available_commands[cmd](*args)

在上面的伪代码中,我定义了两种方法。然后我有一个字典映射动作到命令。然后我查看动作和参数的数据结构,并相应地调用相应的参数。你明白了。