Search code examples
pythonencodingbyte

Is there an equivalent function to the b'' byte literal?


I am working with a text file containing lines of data that include both ASCII and escaped byte data and I am trying to find a function in Python to encode the lines of text into bytes data for sending to another PC over UDP.

The string I am trying to encode is captured OSC data and looks similar to this line:

#bundle\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x008/tracking/trackers/head/position\x00\x00\x00\x00,fff\x00\x00\x00\x00\x00\x00\x00\x00\xbd\xb8\x93\xbd\x80\x00\x00\x00\x00\x00\x004/tracking/trackers/6/position\x00\x00\x00,fff\x00\x00\x00\x00\x00\x00\x00\x00\xbe\xdb\xe9\x9e\x80\x00\x00\x00\x00\x00\x004/tracking/trackers/6/rotation\x00\x00\x00,fff\x00\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004/tracking/trackers/1/position\x00\x00\x00,fff\x00\x00\x00\x00\x00\x00\x00\x00\xbfAO\x80\x80\x00\x00\x00\x00\x00\x004/tracking/trackers/1/rotation\x00\x00\x00,fff\x00\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004/tracking/trackers/4/position\x00\x00\x00,fff\x00\x00\x00\x00<]\x01P\xbfF[\x9d>\xa2\xaa\xf2\x00\x00\x004/tracking/trackers/4/rotation\x00\x00\x00,fff\x00\x00\x00\x00\xc2\xad\xe3\x91A\xbc\xd2\xec@\xff)\xcb\x00\x00\x004/tracking/trackers/5/position\x00\x00\x00,fff\x00\x00\x00\x00>:=\xcd\xbf\x90vV\x80\x00\x00\x00\x00\x00\x004/tracking/trackers/5/rotation\x00\x00\x00,fff\x00\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004/tracking/trackers/2/position\x00\x00\x00,fff\x00\x00\x00\x00<]\x01L\xbf\xa2\x93Y>\xa2\xaa\xf2\x00\x00\x004/tracking/trackers/2/rotation\x00\x00\x00,fff\x00\x00\x00\x00\x00\x00\x00\x00A\xf9Op\x00\x00\x00\x00\x00\x00\x004/tracking/trackers/3/position\x00\x00\x00,fff\x00\x00\x00\x00>\xb28^\xbf\x92\xc6L>\xea\x81o\x00\x00\x004/tracking/trackers/3/rotation\x00\x00\x00,fff\x00\x00\x00\x00BJ\xd5.B\xfd\xb4(C#\xcf`'

But when I attempt to encode the string to bytes Python is including new double backslashes in the bytes object:

b1 = b'tracking/trackers/head/position\x00\x00\x00\x00'
b2 = r"tracking/trackers/head/position\x00\x00\x00\x00".encode()

print(b1)
print(b2)

b'tracking/trackers/head/position\x00\x00\x00\x00'
b'tracking/trackers/head/position\\x00\\x00\\x00\\x00' #added double backslashes

How do I parse or encode a string to produce the equivalent as a byte literal in Python 3?


Solution

  • You need to have the correct bytes for it to be able to encode back correctly.

    See the below example:

    b1 = b'tracking/trackers/head/position\x00\x00\x00\x00'
    print(b1)
    print(b1.decode())
    print(b1.decode().encode())
    
    b'tracking/trackers/head/position\x00\x00\x00\x00'
    tracking/trackers/head/position
    b'tracking/trackers/head/position\x00\x00\x00\x00'
    

    For an explanation as to why this works, I would recommend reading this answer: What exactly do "u" and "r" string prefixes do, and what are raw string literals?

    Notably:

    A "raw string literal" is a slightly different syntax for a string literal, in which a backslash, , is taken as meaning "just a backslash" (except when it comes right before a quote that would otherwise terminate the literal) -- no "escape sequences" to represent newlines, tabs, backspaces, form-feeds, and so on. In normal string literals, each backslash must be doubled up to avoid being taken as the start of an escape sequence.

    Where you're using the r'stringhere' thats messing with the backslashes.

    Update 1: As for alternatives to using b'' as mentioned in title there is the bytes.decode function I used in the example, the docs for that are here
    Another alternative is the bytes function, docs for that are here
    And an example that below:

    b1 = b'tracking/trackers/head/position\x00\x00\x00\x00'
    print(b1)
    print(bytes(b1.decode(), 'utf-8'))
    print(b1.decode().encode())
    
    b'tracking/trackers/head/position\x00\x00\x00\x00'
    b'tracking/trackers/head/position\x00\x00\x00\x00'
    b'tracking/trackers/head/position\x00\x00\x00\x00'
    

    And I assumed you had the bytes to begin with, otherwise just a normal string would also behave in the manor you require too.

    b1 = 'tracking/trackers/head/position\x00\x00\x00\x00'
    print(b1)
    print(b1.encode())
    
    tracking/trackers/head/position
    b'tracking/trackers/head/position\x00\x00\x00\x00'
    

    Update 2:

    Okay so if you're file wasnt written correctly and the escaped characters are literally just individual characters (not encoded/decoded) and you want to parse them as if they were, you can use the 'unicode-escape' encoding to decode the double escaped codes \\x00 you get when reading.
    Note the encoding to latin1 to maintain the bytes before decoding to whichever encoding it was originally.

    f = open("output.txt", "rb")
    b2 = f.read().decode('unicode-escape').encode('latin1').splitlines()[0] #.decode('utf-8', errors='ignore')
    f.close()
    
    b"#bundle\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x008/tracking/trackers/head/position\x00\x00\x00\x00,fff\x00\x00\x00\x00\x00\x00\x00\x00\xbd\xb8\x93\xbd\x80\x00\x00\x00\x00\x00\x004/tracking/trackers/6/position\x00\x00\x00,fff\x00\x00\x00\x00\x00\x00\x00\x00\xbe\xdb\xe9\x9e\x80\x00\x00\x00\x00\x00\x004/tracking/trackers/6/rotation\x00\x00\x00,fff\x00\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004/tracking/trackers/1/position\x00\x00\x00,fff\x00\x00\x00\x00\x00\x00\x00\x00\xbfAO\x80\x80\x00\x00\x00\x00\x00\x004/tracking/trackers/1/rotation\x00\x00\x00,fff\x00\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004/tracking/trackers/4/position\x00\x00\x00,fff\x00\x00\x00\x00<]\x01P\xbfF[\x9d>\xa2\xaa\xf2\x00\x00\x004/tracking/trackers/4/rotation\x00\x00\x00,fff\x00\x00\x00\x00\xc2\xad\xe3\x91A\xbc\xd2\xec@\xff)\xcb\x00\x00\x004/tracking/trackers/5/position\x00\x00\x00,fff\x00\x00\x00\x00>:=\xcd\xbf\x90vV\x80\x00\x00\x00\x00\x00\x004/tracking/trackers/5/rotation\x00\x00\x00,fff\x00\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x004/tracking/trackers/2/position\x00\x00\x00,fff\x00\x00\x00\x00<]\x01L\xbf\xa2\x93Y>\xa2\xaa\xf2\x00\x00\x004/tracking/trackers/2/rotation\x00\x00\x00,fff\x00\x00\x00\x00\x00\x00\x00\x00A\xf9Op\x00\x00\x00\x00\x00\x00\x004/tracking/trackers/3/position\x00\x00\x00,fff\x00\x00\x00\x00>\xb28^\xbf\x92\xc6L>\xea\x81o\x00\x00\x004/tracking/trackers/3/rotation\x00\x00\x00,fff\x00\x00\x00\x00BJ\xd5.B\xfd\xb4(C#\xcf`'"