我有一些任务存储在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)“
以及之后的评估..任何想法都是最好的方式或更好的模式来完成这种任务?
答案 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
。这是最好的方法。
答案 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)
在上面的伪代码中,我定义了两种方法。然后我有一个字典映射动作到命令。然后我查看动作和参数的数据结构,并相应地调用相应的参数。你明白了。