String 在模板字符串中求值

String 在模板字符串中求值,string,templates,python,String,Templates,Python,我正在考虑将一个相当笨拙的bash脚本移植到python上,但我一直在考虑如何处理以下方面:脚本的要点是根据动态获取的数据生成一个png图像。bash脚本获取数据,并构建一个非常长的convert实用程序调用,其中包含许多选项。python的模板字符串似乎是一个很好的解决方案(我更愿意留在标准库中,因为我将部署到共享宿主),但我发现您无法像在bash中那样计算表达式: >>> from string import Template >>> s = Templa

我正在考虑将一个相当笨拙的bash脚本移植到python上,但我一直在考虑如何处理以下方面:脚本的要点是根据动态获取的数据生成一个png图像。bash脚本获取数据,并构建一个非常长的
convert
实用程序调用,其中包含许多选项。python的模板字符串似乎是一个很好的解决方案(我更愿意留在标准库中,因为我将部署到共享宿主),但我发现您无法像在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
因为我的bash脚本很大程度上依赖于这种算法(否则要跟踪的变量数量将成倍增加),所以我想知道是否有办法在python中模拟这种行为。我看到,在提出大致相同的问题时,有一条评论,内容如下:

这将是非常不和谐的,因为这是违反直觉的——字符串只是 字符串,它们不应该运行代码

如果是这样的话,用什么更惯用的方法来解决这个问题?
对于上面链接的问题,建议的答案是将字符串格式与
%
语法或
format()
函数一起使用,但我认为这对字符串中的变量数量(大约50个)不起作用。

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

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

这个问题的Pythonic解决方案是忽略字符串格式,并将参数列表传递给其中一个函数,例如

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

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

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


如果Jinja由于某种原因不适合您,那么请查看Python wiki,它已经发布了。其中有一个非常轻量级的类,它只是一个类,似乎可以完全满足您的需要。

任务并没有那么难,为什么不做一些有趣的编码呢?这是一个函数,它几乎可以满足你的需要

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

我认为公式应该是模板本身的一部分。老板希望有一些模板来呈现,而不是硬编码的程序行。我在最后一段提到了这一点。我有大约50个变量要插入到一个80行的字符串中,我认为
.format()
习惯用法不太合适。你会不同意吗?@Mayli不,甚至不是那样,只是我认为这不切实际,以至于不值得从bash翻译过来;你觉得怎么样?@NiklasB。是的,这将是我的首选,因为我有
$((2*$margin+$width))
等实例,这些实例都需要在
.format()
方法中指定它们自己的名称。我不认为引用是OP的问题。至少没有提到anywhere@NiklasB. 引用不是一个问题,只是因为我还没有翻译成python:)我认为这是解决我问题的一个比使用模板库更好的解决方案,因为它不需要外部代码,并且避免了显式生成一个巨大的字符串。@mszep:很公平,我当时可能误解了这个问题;)谢谢你的回答,但是,我认为为了满足我的需要,使用外部模板库(无论多么轻量级)有点过分,特别是因为我的字符串只构建了一次,并且不包含任何复杂的逻辑,只包含值的替换。这真的很酷,我没有想过这样做。。。一个缺点是,对于大型模板,它会变得很慢,因为您会反复将“模板”分配给其自身的修改版本。然而,我认为我更喜欢@larsmans的答案,因为它完全避免了显式构建字符串的需要。不过还是要谢谢你@mszep你可以把这个标记为pythonic。