Python 2 vs Python 3: DevString with bytes

Hi all,

I noticed an intriguing behavior of PyTango running within a Python 3 environment.

Scenario

An old, existing C++ server to control a RS232 serial line. The server has a DevSerReadString method to read chars from the serial line ; Tango output data type is DevString. The equipment connected to the serial line sends binary data.

Problem

When calling the command from a Python 2 client, everything works fine -- the returned string corresponds to the bytes sent by the equipment. When calling the command from a Python 3 client, None is returned.

Minimal example to reproduce the problem

  • Server in Python 2

    from tango.server import run
    from tango.server import Device
    from tango.server import attribute, command
    
    class BytesTest(Device):
        @command(dtype_out=str)
        def bytes_str1(self):
            return "binary_data\xee\xff"
    
    if __name__ == "__main__":
        run((BytesTest,))
  • Python 3 client

     Python 3.7.1 (default, Dec 14 2018, 19:28:38) 
     [GCC 7.3.0] :: Anaconda, Inc. on linux
     Type "help", "copyright", "credits" or "license" for more information.
     >>> import tango; dev=tango.DeviceProxy("id00/tango/test")
     >>> print(dev.bytes_str1())
     None
     >>> 

Additional information

Of course the problem comes from bytes/unicode handling in Python. It is also probably a bad idea to use DevString for this kind of data transfer, maybe DevVarCharArray would have been better...

According to the PyTango documentation, DevString is encoded as latin-1, but it does not seem to be the case in reality.

>>> s = "binary_data\xee\xff"
>>> print(s)
'binary_dataîÿ'
>>> print(s.encode("latin-1"))
b'binary_data\xee\xff'