#158 serial.write does not work with Python 3.3 when writing a string

v2.7
closed
Chris Liechti
None
8
2015-01-11
2014-02-01
Clark Sann
No

I am using Python 3.3 and SerialIO 2.7. When I try to write a string to a serial port using the following command:

ser.write('MR0000;')

I get the following errors:

Traceback (most recent call last):
File "/Users/Clark/PycharmProjects/TS2000/Main.py", line 14, in GetData
channels = SerialIO.GetChannelData()
File "/Users/Clark/PycharmProjects/TS2000/SerialIO.py", line 191, in GetChannelData
TS2KRawMemoryConfig = TS2K.ReadMemoryConfig(0, 29)
File "/Users/Clark/PycharmProjects/TS2000/SerialIO.py", line 49, in ReadMemoryConfig
ser.write(readCommand)
File "/usr/local/Cellar/python3/3.3.3/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/pyserial-2.7-py3.3.egg/serial/serialposix.py", line 491, in write
File "/usr/local/Cellar/python3/3.3.3/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/pyserial-2.7-py3.3.egg/serial/serialutil.py", line 76, in to_bytes

I am new at Python but I think the problem is that b.append(item) does not accept a string. It only accepts an integer.

Related

Bugs: #158

Discussion

  • Chris Liechti
    Chris Liechti
    2014-02-02

    • Priority: 1 --> 8
     
  • Chris Liechti
    Chris Liechti
    2014-02-02

    with Python 3, pySerial expects "bytes".

    either use the 'b' modifier or the encode method:

    ser.write(b'MR0000;')
    ser.write('MR0000;'.encode('latin1'))

    depending on the device and purpose, one or the other might me better suited.

     
    • Clark Sann
      Clark Sann
      2014-02-02

      Thanks for looking at this so quickly. The documentation still shows that write and writelines takes string data.

      I'll close this but I'm not sure how to do it….

      On Feb 1, 2014, at 6:38 PM, Chris Liechti cliechti@users.sf.net wrote:

      with Python 3, pySerial expects "bytes".

      either use the 'b' modifier or the encode method:

      ser.write(b'MR0000;')
      ser.write('MR0000;'.encode('latin1'))

      depending on the device and purpose, one or the other might me better suited.

      [bugs:#158] serial.write does not work with Python 3.3 when writing a string

      Status: open
      Created: Sat Feb 01, 2014 09:27 PM UTC by Clark Sann
      Last Updated: Sat Feb 01, 2014 09:27 PM UTC
      Owner: Chris Liechti

      I am using Python 3.3 and SerialIO 2.7. When I try to write a string to a serial port using the following command:

      ser.write('MR0000;')

      I get the following errors:

      Traceback (most recent call last):
      File "/Users/Clark/PycharmProjects/TS2000/Main.py", line 14, in GetData
      channels = SerialIO.GetChannelData()
      File "/Users/Clark/PycharmProjects/TS2000/SerialIO.py", line 191, in GetChannelData
      TS2KRawMemoryConfig = TS2K.ReadMemoryConfig(0, 29)
      File "/Users/Clark/PycharmProjects/TS2000/SerialIO.py", line 49, in ReadMemoryConfig
      ser.write(readCommand)
      File "/usr/local/Cellar/python3/3.3.3/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/pyserial-2.7-py3.3.egg/serial/serialposix.py", line 491, in write
      File "/usr/local/Cellar/python3/3.3.3/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/pyserial-2.7-py3.3.egg/serial/serialutil.py", line 76, in to_bytes

      I am new at Python but I think the problem is that b.append(item) does not accept a string. It only accepts an integer.
      Sent from sourceforge.net because you indicated interest in https://sourceforge.net/p/pyserial/bugs/158/

      To unsubscribe from further messages, please visit https://sourceforge.net/auth/subscriptions/

       

      Related

      Bugs: #158

  • Chris Liechti
    Chris Liechti
    2014-08-04

    • status: open --> closed
     
  • Strictly speaking, I think this is still a bug (I installed pyserial from pipy using pip a couple of days ago; my installed version 2.7).

    In particular, the documentation says:

    serial.to_bytes(sequence)
        Parameters: sequence  String or list of integers
        Returns:    an instance of bytes
    
    Convert a sequence to a bytes type. This is used to write code that is compatible to Python 2.x and 3.x.
    [..]
    This function is used internally and in the unit tests.
    

    The following shows how the bug happens:

    >>> import serial
    >>> serial.to_bytes('hello')
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-19-d9a9676f2521> in <module>()
    ----> 1 serial.to_bytes('hello')
    
    /opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/serial/serialutil.py in to_bytes(seq)
         74         b = bytearray()
         75         for item in seq:
    ---> 76             b.append(item)  # this one handles int and str for our emulation and ints for Python 3.x
         77         return bytes(b)
         78
    
    TypeError: an integer is required
    

    One possible fix is as follows:

    def to_bytes(seq):
        """convert a sequence to a bytes type"""
        if isinstance(seq, bytes): # this will catch str and bytes in Python 2.*
            return seq
        elif isinstance(seq, str): # this will catch str in Python 3.*
            # it is hard to know what encoding might be intended..
            # utf-8 will work for sure and is compatible with ascii..
            return bytes(seq,encoding='utf-8')
        elif isinstance(seq, bytearray):
            return bytes(seq)
        elif isinstance(seq, memoryview):
            return seq.tobytes()
        else: # this one handles int for our emulation
            b = bytearray()
            for item in seq:
                b.append(item)  
            return bytes(b)
    

    Another possible fix is to change the documentation.
    It is not entirely clear to me what is really the intended behavior of to_bytes: There seems to be a difference in the implementation of Serial for IronPython and Jython than the rest, e.g., PosixSerial, where to_bytes() is called for the argument of write and it is beyond my knowledge to understand why this is so. In any case, there is an inconsistency, which IMHO should be removed.

     
    Last edit: Csaba Szepesvari 2015-01-11