Question

I've converted a older Python script with the Python 2to3 tool to make it compatible with Blender. The script makes communication possible between Blender3D and a OMRON PLC. However after conversion the script gives the following error in the Blender 3D console:

TypeError: 'str' does not support the buffer interface

This occurs in the following lines:

def _send(self,  raw):
    self.sock.send( raw)
    #print ' Send:' + repr(raw)
def _recieve(self):
    pr = self.sock.recv(8)
    length = binstr2int( pr[4:8])
    r = pr + self.sock.recv( length)
    #print ' Recv:' + repr(r)
    return r

I've searched the problem using google and it seems its a problem that occurs when you convert or use an older script for Python 3+. Adding .encode() and .decode() to the objects where the problems occur has not helped either.

def _send(self,  raw):
    self.sock.send( raw.encode())
    #print ' Send:' + repr(raw)
def _recieve(self):
    pr = self.sock.recv(8).decode()
    length = binstr2int( pr[4:8])
    r = pr + self.sock.recv( length)
    #print ' Recv:' + repr(r)
    return r

This gives a different kind of error:

TypeError: can't convert 'bytes' to str implicitly

The script was not made by me, I'm simply using it for a school project to make communication possible between software (Blender3D) and hardware (PLC).

Help would be much appreciated, thanks.

I've put the converted version of the script here.

Was it helpful?

Solution

  1. Bytes-only operations like self._send(c1.raw) needs to be encoded correctly. Use either self._send(bytes(c1.raw, "utf-8")) or self._send(c1.raw.encode("utf-8"))

    However, since your classes like FinsTCPframe is actually operating bytes stream instead of unicode literals, I'd suggest to just stick to bytes (append b in front of any affected string constants, like b'' instead of ''

  2. ord() around an item of a bytes instance (for example, if s is a bytes instance, s[i] is the item) should be removed, since retrieving one element from bytes in Python 3.x is already a int instance. If you are not 100% sure what's inside your ord() call, try this (dirty) workaround:

    safe_ord = lambda c: ord(c) if isinstance(c, str) else c

    And replace corresponding ord() with safe_ord()

  3. chr() in python 3 returns a str, but if you need bytes instead, try this:

    bytes_chr = lambda x: bytes([x]) (from this stackoverflow question)

    And replace corresponding chr() with bytes_chr()

  4. Division / is resulting in a float by default, so if you want to retain the old behavior, double the symbol: //

A full list of porting guide can be found on the official python docs site, consult this if you need to do the porting work in the future :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top