Python sockets error TypeError: a bytes-like object is required, not ‘str’ with send function

Each Answer to this Q is separated by one/two green lines.

I am trying to create a program that will open a port on the local machine and let others connect into it via netcat. My current code is.

s = socket.socket()
host="127.0.0.1"
port = 12345
s.bind((host, port))

s.listen(5)
while True:
    c, addr = s.accept()
    print('Got connection from', addr)
    c.send('Thank you for connecting')
    c.close()

I am new to Python and sockets. But when I run this code it will allow me to send a netcat connection with the command:

nc 127.0.0.1 12345

But then on my Python script I get the error for the c.send:

TypeError: a bytes-like object is required, not 'str'

I am basically just trying to open a port, allow netcat to connect and have a full shell on that machine.

The reason for this error is that in Python 3, strings are Unicode, but when transmitting on the network, the data needs to be bytes instead. So… a couple of suggestions:

  1. Suggest using c.sendall() instead of c.send() to prevent possible issues where you may not have sent the entire msg with one call (see docs).
  2. For literals, add a 'b' for bytes string: c.sendall(b'Thank you for connecting')
  3. For variables, you need to encode Unicode strings to byte strings (see below)

Best solution (should work w/both 2.x & 3.x):

output="Thank you for connecting"
c.sendall(output.encode('utf-8'))

Epilogue/background: this isn’t an issue in Python 2 because strings are bytes strings already — your OP code would work perfectly in that environment. Unicode strings were added to Python in releases 1.6 & 2.0 but took a back seat until 3.0 when they became the default string type. Also see this similar question as well as this one.

You can decode it to str with receive.decode('utf_8').

You can change the send line to this:

c.send(b'Thank you for connecting')

The b makes it bytes instead.

An alternative solution is to introduce a method to the file instance that would do the explicit conversion.

import types

def _write_str(self, ascii_str):
    self.write(ascii_str.encode('ascii'))

source_file = open("myfile.bin", "wb")
source_file.write_str = types.MethodType(_write_str, source_file)

And then you can use it as source_file.write_str("Hello World").


The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .