Domenico Catino
Domenico Catino

Reputation: 33

List of ascii ordinals to string with python

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

Answers (3)

jfs
jfs

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

timgeb
timgeb

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

idjaw
idjaw

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

Related Questions