2017-02-02 8 views
2

Итак, я пытаюсь преобразовать код из Python 2.7 в Python 3, и кажется, что что-то изменилось. Я пытаюсь получить двоичные данные через сокет, и теперь он не работает. Вот мой код.TypeError: Невозможно преобразовать объект 'bytes' в str неявно при работе с сокетами

EDIT: Я добавил код отправки. Кроме того, мне не очень нравится то, как это работает прямо сейчас, это слишком сложно. Если можно, было бы неплохо иметь лучший способ отправки/получения данных.

def recv(self): 
    # Receive the length of the incoming message (unpack the binary data) 
    dataLength = socket.ntohl(struct.unpack("I", self._recv(4))[0]) 

    # Receive the actual data 
    return self._recv(dataLength) 

def _recv(self, length): 
    try: 
     data = '' 
     recvLen = 0 
     while recvLen < length: 
      newData = self.sock.recv(length-recvLen) 

      if newData == '': 
       self.isConnected = False 
       raise exceptions.NetworkError(errors.CLOSE_CONNECTION, errno=errors.ERR_CLOSED_CONNECTION) 

      data = data + newData # TypeError here 
      recvLen += len(newData) 

     return data 
    except socket.error as se: 
     raise exceptions.NetworkError(str(se)) 

def send(self, data): 
    if type(data) is not str: 
     raise TypeError() 

    dataLength = len(data) 

    # Send the length of the message (int converted to network byte order and packed as binary data) 
    self._send(struct.pack("I", socket.htonl(dataLength)), 4) 

    # Send the actual data 
    self._send(data, dataLength) 

def _send(self, data, length): 
    sentLen = 0 
    while sentLen < length: 
     try: 
      amountSent = self.sock.send(data[sentLen:]) 
     except Exception: 
      self.isConnected = False 
      raise exceptions.NetworkError(errors.UNEXPECTED_CLOSE_CONNECTION) 

     if amountSent == 0: 
      self.isConnected = False 
      raise exceptions.NetworkError(errors.UNEXPECTED_CLOSE_CONNECTION) 

     sentLen += amountSent 
+0

всегда ставить ** ** сообщение ПОЛНОЙ ошибки ** ВОПРОСА **. Есть и другая полезная информация, т.е. какая линия делает проблему. – furas

+0

Вы, вероятно, захотите прочитать http://python3porting.com/problems.html#bytes-strings-and-unicode – Amber

+0

@furas Вопрос содержит всю необходимую информацию, если вы посмотрите на код, я разместил комментарий, где точное ошибка происходит. Сообщение об ошибке находится в заголовке. Что еще вы искали? – ken596

ответ

4

Python 3 передает данные в виде байтов, так что вы должны декодировать нанизывать

data = data + newData.decode('utf-8') 

# or 

data = data + newData.decode('ascii') 

если вам нужны данные байт, то использовать

data = b'' 

и держать без .decode()

data = data + newData 

EDIT: для нового кода в вопросе.

Когда вы отправляете, вам нужно преобразовать/закодировать строку в байты и после этого получить ее длину. Родные символы имеют длину 1 как unicode, но они могут использовать 2 байта (или более).

Когда вы получаете, вы должны работать с байтами b'' и в конце конвертировать/декодировать байты в строку снова.

Смотрите комментарии # <-- в коде

def send(self, data): 
    if not isinstance(data, str): # <-- prefered method 
    #if type(data) is not str: 
     raise TypeError() 

    data = data.encode('utf-8') # <-- convert to bytes 

    # get size of bytes 
    dataLength = len(data) 

    # Send the length of the message (int converted to network byte order and packed as binary data) 
    self._send(struct.pack("I", socket.htonl(dataLength)), 4) 

    # Send the actual data 
    self._send(data, dataLength) 


def recv(self): 
    # Receive the length of the incoming message (unpack the binary data) 
    dataLength = socket.ntohl(struct.unpack("I", self._recv(4))[0]) 

    # Receive the actual data 
    return self._recv(dataLength).decode('utf-8') # <-- convert to string again 

def _recv(self, length): 
    try: 
     data = b'' # <-- use bytes 
     recvLen = 0 
     while recvLen < length: 
      newData = self.sock.recv(length-recvLen) 

      #if newData == b'': # <-- use bytes 
      if not newData: # <-- or 
       self.isConnected = False 
       raise exceptions.NetworkError(errors.CLOSE_CONNECTION, errno=errors.ERR_CLOSED_CONNECTION) 

      data = data + newData # TypeError here 
      recvLen += len(newData) 

     return data 
    except socket.error as se: 
     raise exceptions.NetworkError(str(se))