0

Been struggling to get this to work because I can't use return in a while loop that is not going to end.

In a nutshell, I'm receiving a message in a socket client in one function receive() (the endless loop) and need to pass the result of that incoming message to main(). Trying to use yield, since I'm not sure what else would achieve this. I created another function to try and capture the yield in the receive() function.

I know the initial message reaches the server because it outputs the message, and I know the client is receiving the server's confirmation message because it's printing it. I just am having no luck passing that data to main(), so the rest of the code won't work right.

I'm very new to this, so I'm probably doing this horribly wrong. I should be using classes to share data more easily, but don't grasp them enough yet. Hopefully using yield or something else can get around that.

receive function:

def receive():
    while True:
        try:
            incoming = client.recv(2048).decode(FORMAT)
            if 'RECEIVED' in incoming:
                confirmation = 'confirmed'
                yield confirmation
            print(incoming)
        except:
            print("Connection interrupted.")
            client.close()
            break

#------------
# also tried
#------------
def receive():
    while True:
        try:
            incoming = client.recv(2048).decode(FORMAT)
            if 'RECEIVED:COMPLETE' in incoming:
                confirmation = 'confirmed'
            else:
                confirmation = 'unconfirmed'
            yield confirmation
        except:
            print("Connection interrupted.")
            client.close()
            break

return function:

def pass_return(passed_return_value):
    passed_return_value

main function (with various tests)

def main():
    pass_return(receive())
    # Bunch of code
        if something == True:
            send("some message")
            time.sleep(.25)
            try:
                if confirmation == 'confirmed':
                    # do the business here

#------------
# also tried
#------------
def main():
    # Bunch of code
        if something == True:
            send("some message")
            time.sleep(.25)
            pass_return(receive())
            try:
                if confirmation == 'confirmed':
                    # do the business here

#------------
# also tried
#------------
def main():
    r = pass_return(receive())
    # Bunch of code
        if something == True:
            send("some message")
            time.sleep(.25)
            try:
                if r == 'confirmed':
                    # do the business here

#------------
# even tried
#------------
def main():
    # Bunch of code
        if something == True:
            send("some message")
            time.sleep(.25)
            r = pass_return(receive())
            try:
                if r == 'confirmed':
                    # do the business here

I'm declaring the variable confirmation OUTSIDE of main() and receive() (atop the file where my constants are) or else I get an error of confirmation is undefined.

If I print confirmation in main(), it either prints nothing or None, so my guess is that it's just getting the initial empty value of confirmation and not the yield.

# constants above here
confirmation = str()

# code and such
def pass_return(passed_return_value):
    passed_return_value
def receive():
    #code...
def main():
    #code...

if __name__ == '__main__':
    main()
1
  • Writing code that handles this kind of thing properly, in a non-blocking way, is a very broad topic. You would want to look into how existing frameworks do it (for example, the Discord API for Python). Commented Nov 28, 2021 at 17:07

1 Answer 1

5

Note that Python is single-threaded. If your program is supposed to do nothing else than waiting for a data to arrive on the socket from an external source, and reacting to it, then this would work:

def receive():
    while True:
        try:
            incoming = client.recv(2048).decode(FORMAT)
            if 'RECEIVED' in incoming:
                yield {'status': 'confirmed', 'message': incoming}
            else:
                yield {'status': 'unconfirmed', 'message': incoming}
        except:
            print("Connection interrupted.")
            client.close()
            break

def main():
    for message in receive():
        print(message)

Here, most of this program's time will be spent on client.recv(2048). This is a blocking call. It does not return until the requested number of bytes is received. Nothing else can happen in your program during this time.

As soon as the bytes are received, you can yield, and the for loop inside main() can process the data. When that's done, the program flow will return to client.recv(2048) and sit there.

If you want different things to happen in your program while it also listens for data on that socket, you will need to look into multithreading, and put this code on a background thread.

Sign up to request clarification or add additional context in comments.

8 Comments

The way this program works is it connects to server initially, then it does what it needs, and then it contacts the server to let it know it completes its task, sleeps for a tick, and then checks for confirmation, prints the confirmation and then ends. I do have another script that just waits. I will try this in both. Thanks for the suggestion.
@liquidRock If you have already split things up into a server and a client anyway, run them in separate processes. That's just as good as multihreading, and less hassle.
Yes, the server is in one script in its own environment. The client(s) are each their own script, some in same env, some in different ones. Do you mean to make the receive function a separate process from main in the client using multiprocessing? I assume multiprocessing or multithreading will be needed in client because adding the code it can no longer connect to server when it starts up (I assume it's waiting to receive to grab that yeild).
I don't follow. For one thing, you seem to have your notions of "client" and "server" mixed up. The program that listens on a port and waits for requests is not the client, that's the server. The program that sends requests and receives responses is the client. And no, I did not mean that receive() and main() should be on different threads, read my answer again. I said "If your program is supposed to do nothing else than waiting for a data to arrive on the socket from an external source, and reacting to it, then this would work".
I've managed to get this working in one script without the use of multithreading thanks to some creative positioning of code, so the client script executes what it needs to and then waits for the yield when it needs to, and can still contact the server when required. Others will need multithreading or maybe even asyncio would work to await the yield. Either way, thanks for the help. I'll post results once I solve the rest.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.