0

I have a script that use the module socket inside a python2 script. I would like to upgrade it to a python3 script.

After searching Difference between Python3 and Python2 - socket.send data and Python socket.send encoding, i haven't succed to upgrade to python3.

A similar post TypeError: a bytes-like object is required, not 'str' describes the method sendto that seem to work in python3, but I have no port on this example...

Here is the connection method:

def connect(self):
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    sys.stderr.write("Waiting for connect to %s\n" % (self.uds_filename,))
    while 1:
        try:
            sock.connect(self.uds_filename)
        except socket.error as e:
            if e.errno == errno.ECONNREFUSED:
                time.sleep(0.1)
                continue
            sys.stderr.write("Unable to connect socket %s [%d,%s]\n"
                             % (self.uds_filename, e.errno,
                                errno.errorcode[e.errno]))
            sys.exit(-1)
        break
    print("CONNECTED")
    self.webhook_socket = sock

And this is the send method:

def send(self, message):
    self.webhook_socket.send("%s\x03" % (message))  # message is type 'str'

The question is: How to translate it correctly. It is send to a Klipper service (3D printing), I don t want to change the server side, only the client side (theses two methods) to python3.

This working script can be found at https://github.com/Klipper3d/klipper/blob/master/scripts/whconsole.py

Because this script interract with specific hardware (3D printer), I will tests your answers. The problem I had by testing solutions of python3 was no answers at all without any errors...

By changing the send method to

def send(self, message):
    self.webhook_socket.send(message.encode())

There is just no answer from the klipper server, it may receive as valid only the python2 format. How to send the exact same message (not a working substitute but a replica) ???

EDIT: Answer from Yarin_007:

sock.send(("%s\x03" % (message)).encode())  # Python 2
sock.send(message.encode()+bytes([0x03]))   # Python 3
Vincent Bénet
  • 1,212
  • 6
  • 20
  • As can be seen in the linked question - you need to use `encode` to convert str to bytes when calling `send`. – Steffen Ullrich Mar 19 '23 at 14:15
  • As described in the question, there is no error but is it not working ... Thank a lot for the user that close my question without answering it !!! Typicall SO behavior ... @SteffenUllrich – Vincent Bénet Mar 19 '23 at 23:45
  • Please be clear where exactly your code is not doing what you expect from it. While you have several debug statements in your code to detect what the program is doing, you don't provide any information of the code flow you expect and what happens instead. It is not even clear if the `send` in question gets called in the first place. The question was closed as duplicate because you focused on the `send` and the `send` was obviously wrong and that was changed between Python 2 and Python 3. If there are any more problems with your code which lead to the `send` not even be called - who knows. – Steffen Ullrich Mar 20 '23 at 04:56
  • As mentionned in the question if you read with attention, you will see that it is a migration of a klipper script. The need is to send the exact same data than python2 script. – Vincent Bénet Mar 20 '23 at 09:41
  • I DONT WANT A SUBSTITUTE BUT I NEED A REPLICA (hope is big enough for you) now reopen the question so helpfull people can reach question. @SteffenUllrich – Vincent Bénet Mar 20 '23 at 09:50
  • 1
    I've reopened the question but I doubt that you get much success with the information your currently provide. Still, good luck. – Steffen Ullrich Mar 20 '23 at 19:25
  • 1
    Note that the difference between Python 2 and Python 3 is that you need to use bytes not str in send and therefore you need to encode the message. But the encoded version of `"%s\x03" % (message)` is not `message.encode()` as you show as attempt. It is `"(%s\x03" % (message)).encode()` instead. – Steffen Ullrich Mar 21 '23 at 05:22
  • I have just no answer using `self.webhook_socket.send(("(%s\x03" % (message)).encode())` (The same send in python2 trigger an answer) – Vincent Bénet Mar 21 '23 at 23:21
  • @SteffenUllrich helpfull people has answer... :) – Vincent Bénet Jul 08 '23 at 19:06

1 Answers1

1

You mean you want to send some ascii text and few bytes in python 3?

it's as simple as

self.webhook_socket.send("your string".encode() + bytes([0x03])) # or a longer list of bytes

Python 2: Python 2

Python 3: python 3

You can literally only send bits over packets.... that's just the reality. you can't send "str objects". What humans do to deal with this is either serialization, or, in this case, encoding. The software at the other side only sees a list of bytes. it's not until you "parse" it and decode them (if they're text) that they make sense.

That's a great improvement imo in python 3 over 2 - 2 would implicitly convert the string to a bytes sequence, while in 3 you've got to be explicit.

see also bytearray

I think you simply forgot to append the 0x03 byte at the end of the data. (which is crucial for the protocol, I assume.) (it could be the etx terminator.

Are you sending a json? like:

json encode

Yarin_007
  • 1,449
  • 1
  • 10
  • 17
  • Thank you very much, I test it in few hours on my 3D printer. You have the source code from python 2 in hyperlink in the question (Klipper) Here is an example: ```send('{"params":{"script":"' + code + '"},"id":123,"method":"gcode/script"}')``` (Yes it is json that is sended) – Vincent Bénet Jul 06 '23 at 14:35
  • it says "applications should send JSON encoded messages without the ETX terminator". strange that it it used in your python 2 code. Anyway, let's hope for the best! and check if you understand the way the dict is turned into a json and then into the correct data type (bytes). and get's the last 0x03 byte appended – Yarin_007 Jul 06 '23 at 14:38
  • Here is my project of sending working in python2 but not in python3: https://gitlab.com/vincentBenet/square_printer/-/tree/master/klipper (communicate.py -> send_gcode function - line 26) – Vincent Bénet Jul 06 '23 at 14:40
  • 1
    I don t know how to thank you man! It is working just fine! – Vincent Bénet Jul 08 '23 at 18:38