Reputation: 33
I've got a list of ascii ordinals like:
[102, 114, 97, 110, 99, 101, 115, 99, 111, 0, 0, 0, 0, 0, 0, 0]
now I want to transform this to a string removing the null characters at the end.
I've tried with
contenuto_tag = "".join(map(chr, backdata))
but when I pass it to a function like:
enos.system("php ../trigger_RFID.php %s"%(contenuto_tag))
I've got this error:
TypeError: must be string without null bytes, not str
maybe because there are the null characters at the end.
Upvotes: 2
Views: 1739
Reputation: 414235
In Python 3, to convert a list of ascii ordinals to a bytestring, you could use bytes
constructor directly:
>>> a = [102, 114, 97, 110, 99, 101, 115, 99, 111, 0, 0, 0, 0, 0, 0, 0]
>>> bytes(a)
b'francesco\x00\x00\x00\x00\x00\x00\x00'
To remove trailing zero bytes, you could call .rstrip(b'\0')
:
>>> bytes(a).rstrip(b'\0')
b'francesco'
If the input should stop at the first zero byte (like C strings -- NUL terminated):
>>> import ctypes
>>> ctypes.create_string_buffer(bytes(b)).value
b'francesco'
To remove all zero bytes (wherever they are), call .replace()
:
>>> bytes(a).replace(b'\0', b'')
b'francesco'
To get a Unicode string, call .decode('ascii')
:
>>> bytes(a).rstrip(b'\0').decode('ascii')
'francesco'
To make it work on both Python 2 and 3, use bytearray()
instead bytes()
:
>>> bytearray(a).rstrip(b'\0').decode('ascii')
'francesco'
The performance of these methods is comparable or better than bytearray(filter(None, a))
solution from @timgeb's answer.
Upvotes: 0
Reputation: 78690
Filter out the null bytes first (Python 2 version):
>>> a = [102, 114, 97, 110, 99, 101, 115, 99, 111, 0, 0, 0, 0, 0, 0, 0]
>>> str(bytearray(filter(None, a)))
'francesco'
Alternative way to do it:
>>> ''.join(map(chr, filter(None, a)))
'francesco'
Some timings:
In [13]: a = a*1000
In [14]: timeit ''.join(chr(i) for i in a if i)
1000 loops, best of 3: 1.44 ms per loop
In [15]: timeit str(bytearray(filter(None, a)))
1000 loops, best of 3: 259 µs per loop
In [16]: timeit ''.join(map(chr, filter(None, a)))
1000 loops, best of 3: 911 µs per loop
edit:
The bytearray
approach that works on both Python 2/3 versions looks like this:
>>> bytearray(filter(None, a)).decode('ascii')
'francesco'
Upvotes: 6
Reputation: 26578
Use a comprehension instead and only do your chr
on non 0:
a = [102, 114, 97, 110, 99, 101, 115, 99, 111, 0, 0, 0, 0, 0, 0, 0]
b = ''.join(chr(i) for i in a if i)
print(b) # outputs francesco
Upvotes: 6