【发布时间】:2017-07-29 04:00:55
【问题描述】:
我想在 python3 上使用原始字节对象执行 sprintf,而无需为 %s 进行任何手动转换。因此,将字节对象作为“模板”,加上任意数量的任何类型的对象并返回渲染的字节对象。这就是 python 2 的 sprintf % 运算符一直以来的工作方式。
b'test %s %s %s' % (5, b'blah','strblah') # python3 ==> error
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: %b requires bytes, or an object that implements __bytes__, not 'int'
def to_bytes(arg):
if hasattr(arg,'encode'): return arg.encode()
if hasattr(arg,'decode'): return arg
return repr(arg).encode()
def render_bytes_template(btemplate : bytes, *args):
return btemplate % tuple(map(to_bytes,args))
render_bytes_template(b'this is how we have to write raw strings with unknown-typed arguments? %s %s %s',5,b'blah','strblah')
# output: b'this is how we have to render raw string templates with unknown-typed arguments? 5 blah strblah'
但在 python 2 中,它只是内置的:
'example that just works %s %s %s' % (5,b'blah',u'strblah')
# output: 'example that just works 5 blah strblah'
有没有办法在 python 3 中做到这一点,但仍能达到与 python 2 相同的性能?请告诉我我错过了什么。这里的后备是在 cython 中实现(或者是否有 Python 3 的库可以帮助实现这一点?)但除了字符串对象的隐式编码之外,仍然没有看到为什么它从标准库中删除。我们不能只添加一个像 format_any() 这样的字节方法吗?
顺便说一句,这可没这么简单:
def render_bytes_template(btemplate : bytes, *args):
return (btemplate.decode() % args).encode()
我不仅不想做任何不必要的编码/解码,而且字节参数是repr'd而不是被原始注入。
【问题讨论】:
-
请注意,Python 3 现在可以保护您免受错误以及隐藏在 Python 2 中的水线之下的错误。例如,尝试打开
'unicode: %s' % (u'Ünîcódæ',)以获取大小。
标签: python python-3.x templates incompatibility