I want to do sprintf on python3 but with raw bytes objects, without having to do any manual conversions for the %s to work. So, take a bytes object as a 'template', plus any number of objects of any type and return a rendered bytes object. This is how python 2's sprintf % operator has always worked.
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'
But in python 2, it's just built in:
'example that just works %s %s %s' % (5,b'blah',u'strblah')
# output: 'example that just works 5 blah strblah'
Is there a way to do this in python 3 but still achieve the same performance of python 2? Please tell me I'm missing something. The fallback here is to implement in cython (or are there libraries out there for python 3 that help in this?) but still not seeing why it was removed from the standard library other than the implicit encoding of the string object. Can't we just add a bytes method like format_any()?
By the way, it's not as simple as this cop-out:
def render_bytes_template(btemplate : bytes, *args):
return (btemplate.decode() % args).encode()
Not only do I not want to do any unnecessary encode/decoding, but the bytes args are repr'd instead of being injected raw.
'unicode: %s' % (u'Ünîcódæ',)
on for size for example. – Yoga'unicode: %s' % u'Ünîcódæ'.encode()
. Good work PSF. – Proceeds