1

I have a program that accepts coordinates over UDP, moves some equipment around, and then replies when the job is done.

I seem to have the same issue as this guy:

Python sendto doesn't seem to send

My code is here:

import socket
import struct
import traceback
def main():


    sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    sock.bind(('',15000))
    reply_sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)


    while True:
        try:
            data,addr = sock.recvfrom(1024)
            if data is not None:
                try:
                    coords = struct.unpack('>dd',data)

                    #Stuff happens here 

                    print(f'moved probe to {coords}')

                    reply_sock.sendto(bytearray.fromhex('B'),('10.0.0.32',15001))
                except:
                    traceback.print_exc()
                    try:
                        reply_sock.sendto(bytearray.fromhex('D'),('10.0.0.32',15001))
                    except:
                        traceback.print_exc()
                    break
        except:
            pass

The program behaves as though the sendto call is just passed over; it accepts the packet, executes the print statements, and loops back around (It can execute the loop multiple times but never replies). I'm looking at wireshark and no packets are ever sent outbound. No errors are ever thrown.

Any ideas why this is happening?

scs675
  • 15
  • 6

1 Answers1

0

From the documentation:

The string must contain two hexadecimal digits per byte, with ASCII whitespace being ignored.

So this happens:

$ python3
Python 3.6.6 (default, Sep 12 2018, 18:26:19) 
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> bytearray.fromhex('B')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: non-hexadecimal number found in fromhex() arg at position 1
>>> 

Try this:

reply_sock.sendto(bytearray.fromhex('0B'),('10.0.0.32',15001))

if that's what you mean.

Note that your except is catching all the exceptions, not just the ones you're expecting, so you're not seeing the error you're causing. Consider using something like except OSError here instead.

Also, think about reducing the amount of code in your try sections:

coords = struct.unpack('>dd',data)

#Stuff happens here 

print(f'moved probe to {coords}')

bytes_to_send = bytearray.fromhex('0B')
try:
    reply_sock.sendto(bytes_to_send,('10.0.0.32',15001))
except IOError as e1:
    print(e1)
    traceback.print_exc()

    bytes_to_send = bytearray.fromhex('0D')
    try:
        reply_sock.sendto(bytes_to_send,('10.0.0.32',15001))
    except IOError as e2:
        print(e2)
        traceback.print_exc()
        break

This way you're protecting only the code which you want to.

Tim
  • 9,171
  • 33
  • 51
  • Thanks a lot, that extra digit did the trick. But I'm confused by your explanation of my except statement. If except is catching all errors, why didn't it catch the issue? – scs675 Oct 24 '18 at 16:53
  • Looking at the code, you said you're seeing the `print()` so it's getting there. Then I'd expect the first call to `bytearray.fromhex` to drop you into the first `except` section, so you get to `traceback.print_exc()` and then the next `try` section would hit another error with `bytearray.fromhex` so you'd go into the next `except` section and reach another `traceback.print_exc()`. Does that fit with what you see? – Tim Oct 24 '18 at 17:03
  • The alternative I suggested it would have caused the `ValueError` from the `bytearray.fromhex` not to have been trapped, so you'll have noticed it before, rather than it being hidden, and you assuming that the `sendto` was causing the problem. – Tim Oct 24 '18 at 17:06
  • So I'm guessing what happened is that if you noticed an error taking place, you didn't realise that it was a `ValueError` caused by `bytearray.fromhex`, rather than an `OSError` caused by `sendto`. That's why it's often helpful to put as little as possible into `try` sections and/or be really specific about what you're catching. – Tim Oct 24 '18 at 17:12
  • I took a look at the exception documentation; what didn't make sense to me was that traceback.print_exc() wasn't printing anything. This was the source of my confusion. Why didn't the exception end up getting printed? – scs675 Oct 24 '18 at 17:28