2

I'm considering porting a rather unwieldy bash script to python but I'm stuck on how to handle the following aspect: The point of the script is to generate a png image depending on dynamically fetched data. The bash script grabs the data, and builds a very long invocation of the convert utility, with lots of options. It seemed like python's template strings would be a good solution (I would vastly prefer to stay within the standard library, since I'll be deploying to shared hosting), but I discovered that you can't evaluate expressions as you can in bash:

>>> 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

Since my bash script depends quite heavily on such arithmetic (otherwise the number of variables to keep track of would increase exponentially) I'd like to know if there's a way to emulate this behavior in python. I saw that this question, asking roughly the same, has a comment, reading:

This would be very unPythonic, because it's counterintuitive -- strings are just strings, they shouldn't run code!

If this is the case, what would be a more idiomatic way to approach this problem? The proposed answer to the question linked above is to use string formatting with either the % syntax or the format() function, but I don't think that would work well with the number of variables in my string (around 50).

4

4 回答 4

3

为什么不使用内置的字符串格式?

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
于 2012-05-28T22:55:20.403 回答
2

您可能需要一个更好的模板引擎。Jinja2支持这种东西等等。我不认为标准库有任何同样强大的功能,但据我所知,该库是纯 Python,因此您只需复制它即可将其集成到您的应用程序中。

如果 Jinja 由于某种原因不适合您,请查看 Python wiki,其中有专门针对这些类型的库的部分。其中包括非常轻量级的Templite,它只是一个类,似乎完全可以满足您的需求。

于 2012-05-28T23:01:38.100 回答
2

这个问题的 Pythonic 解决方案是忘记字符串格式并将参数列表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"])

这样,无需构建单个字符串,也无需担心引用。

于 2012-05-28T22:57:11.820 回答
2

这个任务并不难,你为什么不做一些有趣的编码呢?这里的功能几乎可以满足您的需求。

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
于 2012-05-28T23:34:04.947 回答