我正在編寫一個腳本,它接收兩個數據列表並查找差異,以便將數據更新到數據庫中。
這些列表是非同類的:一個是數據庫對象列表,另一個是字典列表。
由於很多原因,此工具提供了在應用更改之前預覽差異列表的機會。
分析預覽後,如果主持人接受更新,則會應用更改。
這意味着包含大量循環和條件測試的腳本將生成預覽列表(投放到輸出頁面)和更改列表。
Python腳本編制策略:兩次運行腳本vs excec
在開發的第一個階段,我編寫了一個腳本,它將以兩種模式運行:'預覽'和'更新'。
該腳本執行所有循環和條件檢查,並且如果在某個點發現更改,則會在「預覽」模式下運行時向輸出字符串添加消息,或者在「更新」模式下運行時執行命令。
然後我就開始想,也許這將是更好的循環和條件檢查的間隔僅通過一次,加入預覽郵件發送到輸出字符串命令的命令列表,每當一個變化中找到。
然後,服務預覽頁面主持人後,如果接受更改,運行第二個腳本,這會是這樣簡單:
def apply_changes(command_list, ...):
for c in command_list:
try:
exec(c)
except Exception, err:
logger.error('Something went wrong while executing command %s: %s', c, err)
raise Exception, err
問:將確定切換到第二腳本的版本?哪些警告/錯誤/奇怪行爲會涉及?
我一直在問almost the same question under the language-agnostic tag,
因爲我比它的實現更感興趣的是考慮問題的algorithmical點。
但是更多地關注實現的觀點,似乎與Python相比,此腳本的第二個版本性能更好,比第一個版本更容易維護。
有什麼理由讓我更喜歡第一個版本?
編輯:添加一些代碼,以更加明確的問題。
第一版本代碼的摘錄可能類似於此函數(用於更簡單的情況,其中比較的值都是字符串),如果滿足某些特定條件,則由嵌套for循環內的其他函數調用:
def update_text_field(object, old_value, new_value, field_name, mode):
....
if old_value != new_value:
if mode is 'preview': output += print_old_new_values(old_value, new_value, field_name)
if mode is 'update':
if hasattr(object, field_name):
setattr(object, field_name, new_value)
object.save()
else:
...
....
在第二個版本,此摘錄會變成這樣:
def update_text_field(object, old_value, new_value, field_name, mode):
....
if old_value != new_value:
output_list.append(print_old_new_values(old_value, new_value, field_name))
command_list.append(generate_command(command, old_value, new_value, field_name))
...
如果你可以掛鉤的變化,爲什麼不來構建的變化,而不是蟒蛇命令列表的隊列? – Odomontois 2012-03-02 00:25:05
'command_list'從哪裏來?這個'exec'看起來像是一個潛在的安全漏洞,可以通過某種你可以定義的應用函數來輕鬆避免。 – wim 2012-03-02 00:26:06
@wim:從腳本本身生成(將清晰地顯示一些代碼) – dolma33 2012-03-02 00:37:27