2012-05-28 65 views
2

我正在考慮將一個相當笨重的bash腳本移植到python,但我堅持如何處理以下方面:該腳本的目的是根據動態獲取的數據生成一個png圖像。 bash腳本抓取數據,並構建了很長時間的convert實用程序調用,並提供了很多選項。這似乎是python的模板字符串將是一個很好的解決方案(我非常喜歡留在標準庫,因爲我將部署到共享主機),但我發現,你不能評估表達式,你可以在bash中:eval模板字符串

>>> from string import Template 
>>> s = Template('The width times one is ${width}') 
>>> s.substitute(width=45) 
'The width times one is 45' 
>>> t = Template('The width times two is ${width*2}') 
>>> t.substitute(width=45) 
# Raises ValueError 

由於我的bash腳本相當嚴重依賴於這樣的運算(變量,否則數量來跟蹤會呈指數級增長),我想知道是否有仿效蟒蛇此行爲的方式。我看到this question,要求大致相同,有一個評論,閱讀:

這將是非常unPythonic,因爲這是違反直覺 - 字符串只是 字符串,它們不應該運行的代碼!

如果是這種情況,那麼處理此問題的更習慣的方法是什麼? 上面鏈接的問題的建議答案是使用%語法或format()函數的字符串格式,但我認爲這對於我的字符串中的變量數量(大約50)沒有效果。

回答

2

的Python化的解決這個問題是忘記有關字符串格式和傳遞的參數的列表subprocess功能之一,例如

# I have no idea about convert's command line usage, 
# so here's an example using echo. 
subprocess.call(["echo", str(1 + 1), "bla"]) 

這樣,就不需要建立單個字符串,也不需要擔心引用。

+0

我不認爲引用是OP的問題。至少,在任何地方都沒有提到 –

+0

@NiklasB。引用不是問題,但僅僅是因爲我還沒有翻譯成python :)我認爲這是一個比使用模板庫更好的解決方案,因爲它不需要外部代碼,並避免了顯式構建巨大串。 – mszep

+0

@mszep:足夠​​公平,我可能誤解了這個問題然後;) –

2

爲什麼不使用內置的字符串格式?

width = 45 
"Width times one is {width}".format(width=width) 
"Width times two is {width}".format(width=2*width) 

導致

Width times one is 45 
Width times two is 90 
+0

我認爲公式應該是模板本身的一部分。 –

+0

老闆想要一些模板來渲染,而不是硬編碼程序的行。 – Mayli

+0

我在最後一段談到了這一點。我有大約50個變量插入到80行字符串中,我不認爲'.format()'成語很適合。你會不同意嗎? – mszep

2

您可能需要更好的模板引擎。 Jinja2支持這種東西和更多。我不認爲標準庫有什麼同樣強大的功能,但是從我的想法來看,這個庫是純Python,所以你可以通過複製它來將它集成到你的應用程序中。

如果由於某種原因Jinja不適合您,請查看Python維基,它有a section specifically for those kinds of libraries。其中之一是輕巧的Templite,這只是一個類,似乎正是你所需要的。

+0

感謝您的回答,但是,我認爲我的需要使用外部模板庫(但輕量級)有點矯枉過正,尤其是因爲我的字符串只是建立並且不包含任何複雜的邏輯,只是取代了值。 – mszep

1

這個任務並不困難,爲什麼不直接編一些編碼來獲得樂趣?這個功能幾乎可以做你想做的。

import re 
def TempEval(template,**kwargs): 
    mark = re.compile('\${(.*?)}') 
    for key in kwargs: 
     exec('%s=%s'%(key,kwargs[key])) 
    for item in mark.findall(template): 
     template=template.replace('${%s}'%item,str(eval(item))) 
    return template 


print TempEval('The width times one is ${width}',width=5) 
#The width times one is 5 
print TempEval('The width times two is ${width*2}',width=5) 
#The width times two is 10 
+0

這真的很酷,我沒有想過這樣做......缺點是它對於大型模板變得很慢,因爲您反覆將「模板」分配給其自身的修改版本。不過,我認爲我更喜歡@larsmans的答案,因爲它避免了根本不需要構建字符串的需要。不過謝謝! – mszep

+0

@mszep You'v標記爲pythonic。 – Mayli