2011-01-10 68 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) 

在上面的僞代碼中,我定義了兩種方法。然後我有一個字典映射行動命令。然後我通過一個行爲和參數的數據結構,並相應地調用適當的參數。你明白了。