title: Chunking bytes (not strings) in Python 2 and 3
body: <p>This is turning out to be trickier than I expected.  I have a byte string:</p>
  
  <pre><code>data = b'abcdefghijklmnopqrstuvwxyz'
  </code></pre>
  
  <p>I want to read this data in chunks of <em>n</em> bytes.  Under Python 2, this is trivial using a minor modification to the <code>grouper</code> recipe from the <code>itertools</code> documentation:</p>
  
  <pre><code>def grouper(iterable, n, fillvalue=None):
      "Collect data into fixed-length chunks or blocks"
      # grouper('ABCDEFG', 3, 'x') --&gt; ABC DEF Gxx
      args = [iter(iterable)] * n
      return (''.join(x) for x in izip_longest(fillvalue=fillvalue, *args))
  </code></pre>
  
  <p>With this in place, I can call:</p>
  
  <pre><code>&gt;&gt;&gt; list(grouper(data, 2))
  </code></pre>
  
  <p>And get:</p>
  
  <pre><code>['ab', 'cd', 'ef', 'gh', 'ij', 'kl', 'mn', 'op', 'qr', 'st', 'uv', 'wx', 'yz']
  </code></pre>
  
  <p>Under Python 3, this gets trickier.  The <code>grouper</code> function as written
  simply falls over:</p>
  
  <pre><code>&gt;&gt;&gt; list(grouper(data, 2))
  Traceback (most recent call last):
    File "&lt;stdin&gt;", line 1, in &lt;module&gt;
    File "&lt;stdin&gt;", line 5, in &lt;genexpr&gt;
  TypeError: sequence item 0: expected str instance, int found
  </code></pre>
  
  <p>And this is because in Python 3, when you iterate over a bytestring (like <code>b'foo'</code>), you get a list of integers, rather than a list of bytes:</p>
  
  <pre><code>&gt;&gt;&gt; list(b'foo')
  [102, 111, 111]
  </code></pre>
  
  <p>The python 3 <code>bytes</code> function will help out here:</p>
  
  <pre><code>def grouper(iterable, n, fillvalue=None):
      "Collect data into fixed-length chunks or blocks"
      # grouper('ABCDEFG', 3, 'x') --&gt; ABC DEF Gxx
      args = [iter(iterable)] * n
      return (bytes(x) for x in izip_longest(fillvalue=fillvalue, *args))
  </code></pre>
  
  <p>Using that, I get what I want:</p>
  
  <pre><code>&gt;&gt;&gt; list(grouper(data, 2))
  [b'ab', b'cd', b'ef', b'gh', b'ij', b'kl', b'mn', b'op', b'qr', b'st', b'uv', b'wx', b'yz']
  </code></pre>
  
  <p>But (of course!) the <code>bytes</code> function under Python 2 does not behave
  the same way.  It's just an alias for <code>str</code>, so that results in:</p>
  
  <pre><code>&gt;&gt;&gt; list(grouper(data, 2))
  ["('a', 'b')", "('c', 'd')", "('e', 'f')", "('g', 'h')", "('i', 'j')", "('k', 'l')", "('m', 'n')", "('o', 'p')", "('q', 'r')", "('s', 't')", "('u', 'v')", "('w', 'x')", "('y', 'z')"]
  </code></pre>
  
  <p>...which is not at all helpful.  I ended up writing the following:</p>
  
  <pre><code>def to_bytes(s):
      if six.PY3:
          return bytes(s)
      else:
          return ''.encode('utf-8').join(list(s))
  
  def grouper(iterable, n, fillvalue=None):
      "Collect data into fixed-length chunks or blocks"
      # grouper('ABCDEFG', 3, 'x') --&gt; ABC DEF Gxx
      args = [iter(iterable)] * n
      return (to_bytes(x) for x in izip_longest(fillvalue=fillvalue, *args))
  </code></pre>
  
  <p>This seems to work, but is this really the way to do it?</p>