Eficient way to split a bytes array then convert it to string in Python
<p>I have a numpy bytes array containing characters, followed by <code>b''</code>, followed by others characters (including weird characters which raise Unicode errors when decoding):</p>

<pre><code>bytes = numpy.array([b'f', b'o', b'o', b'', b'b', b'a', b'd', b'\xfe', b'\x95', b'', b'\x80', b'\x04', b'\x08' b'\x06'])
</code></pre>

<p>I want to get everything before the first <code>b''</code>.</p>

<p>Currently my code is:</p>

<pre><code>txt = []
for c in bytes:
    if c != b'':
        txt.append(c.decode('utf-8'))
    else:
        break
txt = ''.join(txt)
</code></pre>

<p>I suppose there is a more efficient and Pythonic way to do that. Any idea?</p>

<p>I like your way, it is explicit, the <code>for</code> loop is understandable by all and it isn't all that slow compared to other approaches.</p>

<p>Some suggestions I'd make would be to change your condition from <code>if c != b''</code> to <code>if c</code> since a non-empty byte object will be truthy and, *don't name your list <code>bytes</code>, you mask the built-in! Name it <code>bt</code> or something similar :-)</p>

<p>Other options include <code>itertools.takewhile</code> which will grab elements from an iterable as long as a predicate holds; your operation would look like:</p>

<pre><code>"".join(s.decode('utf-8') for s in takewhile(bool, bt))
</code></pre>

<p>This is slightly slower but is more compact, if you're a one-liner lover this might appeal to you.</p>

<p>Slightly faster and also compact is using <code>index</code> along with a slice:</p>

<pre><code>"".join(b.decode('utf-8') for b in bt[:bt.index(b'')])
</code></pre>

<p>While compact it also suffers from readability.</p>

<p>In short, I'd go with the for loop since readability counts as very pythonic in my eyes.</p>

python python-3.x numpy split