88

In Python 3, one can format a string like:

"{0}, {1}, {2}".format(1, 2, 3)

But how to format bytes?

b"{0}, {1}, {2}".format(1, 2, 3)

raises AttributeError: 'bytes' object has no attribute 'format'.

If there is no format method for bytes, how to do the formatting or "rewriting" of bytes?

6 Answers 6

60

As of Python 3.5, % formatting will work for bytes, too!

This was part of PEP 461, authored by Ethan Furman:

PEP: 461
Title: Adding % formatting to bytes and bytearray
Version: $Revision$
Last-Modified: $Date$
Author: Ethan Furman <ethan at stoneleaf.us>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 2014-01-13
Python-Version: 3.5
Post-History: 2014-01-14, 2014-01-15, 2014-01-17, 2014-02-22, 2014-03-25,
               2014-03-27
Resolution:


Abstract
========

This PEP proposes adding % formatting operations similar to Python 2's ``str``
type to ``bytes`` and ``bytearray`` [1]_ [2]_.


Rationale
=========

While interpolation is usually thought of as a string operation, there are
cases where interpolation on ``bytes`` or ``bytearrays`` make sense, and the
work needed to make up for this missing functionality detracts from the overall
readability of the code.


Motivation
==========

With Python 3 and the split between ``str`` and ``bytes``, one small but
important area of programming became slightly more difficult, and much more
painful -- wire format protocols [3]_.

This area of programming is characterized by a mixture of binary data and
ASCII compatible segments of text (aka ASCII-encoded text).  Bringing back a
restricted %-interpolation for ``bytes`` and ``bytearray`` will aid both in
writing new wire format code, and in porting Python 2 wire format code.

Common use-cases include ``dbf`` and ``pdf`` file formats, ``email``
formats, and ``FTP`` and ``HTTP`` communications, among many others.

PEP 461 was accepted by Guido van Rossum on March 27, 2014:

Accepted. Congrats with marshalling yet another quite contentious discussion, and putting up with my last-minute block-headedness!

From this, we can obviously conclude that % is no longer scheduled for deprecation (as was announced with Python 3.1).

Sign up to request clarification or add additional context in comments.

Comments

32

Another way would be:

"{0}, {1}, {2}".format(1, 2, 3).encode()

Tested on IPython 1.1.0 & Python 3.2.3

2 Comments

This doesn't work if your format arguments are bytes.
This does not work when you need to insert hard byte codes in the stream that are not supported by Unicode.
22

I found the %b working best in Python 3.6.2, it should work both for b"" and "":

print(b"Some stuff %b. Some other stuff" % my_byte_or_unicode_string)

3 Comments

it should be %b not %a for byte string, otherwise 'b' prefix is included
It doesn't work in Python 2.7.16 though, so it's not backward-compatible.
It doesn't work with unicode string. Only b'' is supported.
18

Interestingly .format() doesn't appear to be supported for byte-sequences; as you have demonstrated.

You could use .join() as suggested here: http://bugs.python.org/issue3982

b", ".join([b'1', b'2', b'3'])

There is a speed advantage associated with .join() over using .format() shown by the BDFL himself: http://bugs.python.org/msg180449

4 Comments

Thanks! The message by BDFL is great find, too. However, this does not solve formatting of, say, floats. It would be interesting to know if there is any other way besides str(some_bytes).encode()
Understood. A .format() method for bytes does appear to be on track for inclusion in 3.4+
@bernie: But the __format__ method of an object and built-in format return str. How will that work with bytes and encodings?
15

For Python 3.6+ you can use this nice and clean syntax:

f'foo {bar}'.encode() # a byte string

4 Comments

This does formatting on str, not bytes. For example, it won't give the intended result if bar is a bytes object. Or if you want to put non-ASCII byte values in the format string.
@interjay of course there are all sorts of cases, where my solution wouldn't be helpful, including the one you mentioned. But this doesn't negate the fact there are remaining cases, including the one I had, when the solution works.
This should be the accepted answer because describes the simplest and best solution.
This is effectively a duplicate of Schcriher's answer and has the exact same problems.
-4

I've found this to work.

a = "{0}, {1}, {2}".format(1, 2, 3)

b = bytes(a, encoding="ascii")

>>> b
b'1, 2, 3'

1 Comment

This is a duplicate of Schcriher's answer, just using a different encoding process

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.