2011-01-10 67 views
1

我有一些任务存储在数据库中供以后执行。例如,我可以修复发送电子邮件的任务。并由cron执行任务(发送它)。我寻找在db中存储代码以供稍后执行的最佳方式。对于前店它的Python代码原始字符串,比做的eval,而且我必须在这里存储的相对进口..存储代码以供稍后执行的最佳方式(python)

例如用于发送电子邮件,我必须解决的字符串是这样的:从Django中

S =” .core.mail import send_mail \ n send_mail('subj','body','[email protected]',['[email protected]'],fail_silently = False)“

及以后的评估。任何想法做到这一点最好的方式或更好的模式这种任务?

回答

4

你在做什么是一个糟糕的主意,主要是因为你在执行代码时会考虑太多的可变性。一个代码字符串可以做任何事情,我猜只有几种你想存储的任务供以后执行。

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

更加奇特的是,你可以拥有某种带有一堆函数的容器对象,并存储该函数的名称以及其参数。该容器可以像导入Django的send_mail等功能的模块一样简单,就像你的例子。

然后你就可以存储你的示例调用是这样的:

func = 'send_mail' 
args = ('subj', 'body', '[email protected]', ['[email protected]']) 
kwargs = {'fail_silently': False} 

my_call = cPickle.dumps((func, args, kwargs)) 

而且使用这样的:

func, args, kwargs = cPickle.loads(my_call) 

getattr(my_module, func)(*args, **kwargs) 
2

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

编辑

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

handlername;arg1;arg2;arg3;arg4 

接下来使用python读出行并解析它们。例如,这将是一个存储行:

sendmail;[email protected];subject;body 

这将是解析如下:

for line in database: 
    handler, *args = line.split(";") 
    if handler == "sendmail": 
     recipient, subject, body, = args[:3] 
     # do stuff 
    elif handler == "delfile": 
     #etc 
+1

-1:你不会做是不是很有趣。有很多很多东西都是坏主意。什么是更好的想法?你会认为这将是他们可以使用的解决方案吗? – 2011-01-10 23:24:52

+0

我提出了一个想法。 *“我会为每个任务创建一个不同的处理程序(发送邮件,删除文件等)。”* – orlp 2011-01-10 23:26:37

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, ...) 

这种方式,您可以同时具有灵活性,而无需添加处理程序,以触摸的调度任何代码和exec他们但是你并没有在数据库中编写代码细节,这会使得检查/统计更加困难,或者只是没有启动的热修复工作。

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) 

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