1

I am trying to run a function in the background, whilst continuing with said code in python.

The function I want to run in the background is from socket. Looking for specific data to cut the program off.

Here is the function:

def receive():
    host = ""
    port = 13000
    buf = 1024
    addr = (host,port)
    Sock = socket(AF_INET, SOCK_DGRAM)
    Sock.bind(addr)
    (data, addr) = Sock.recvfrom(buf)
    return data

Here is the code I want to run:

while True:
    r = receive()
    if r == "stop":
        break
    #Cannot get past here, because of the function running.
    #Should loop over and over, until stop data is received
    print "Running program"

I have tried threading, with r = threading.Thread(target=receive()) with no joy.

Jonathan Davies
  • 882
  • 3
  • 12
  • 27

2 Answers2

1

You can't return to the invoking thread from an invoked thread's target function. Instead, you need some inter-thread communication system. Below, is an example using Python's Queue to pass received datagrams between the two threads. I've used a threading.Event to signal when the receiver thread should stop.

#!/usr/bin/env python

import socket
import threading
from queue import Empty, Queue


class DatagramReceiver(threading.Thread):
    def __init__(self, stop, queue):
        super().__init__()
        self._stop = stop
        self._queue = queue

    def run(self):
        with socket.socket(AF_INET, SOCK_DGRAM) as sock:
            sock.bind(('', 13000))
            while not self._stop.is_set():
                data = sock.recvfrom(1024)[0]
                if data == 'stop':
                    self._stop.set()
                    break
                self._queue.put(data)


def main():
    stop = threading.Event()
    queue = Queue()

    reader = DatagramReceiver(stop, queue)
    reader.deamon = True
    reader.start()

    while not stop.is_set():
        user_input = input('Press RETURN to print datagrams, or q quit')
        if user_input == 'q':
            break
        while True:
            try:
                datagram = queue.get_nowait()
            except Empty:
                break
            print(datagram)

    stop.set()
    reader.join()
Peter Sutton
  • 1,145
  • 7
  • 20
  • The **stop** message should come from another python script. I am not sure how I would implement your script with this in mind. @PeterSutton – Jonathan Davies Dec 14 '14 at 23:31
  • I've edited the code so that a 'stop' message will cause the the worker thread to stop (and in turn the main thread). It's still a good idea for the main thread to be able to stop the worker thread cleanly (hence I still use the stop Event). – Peter Sutton Dec 16 '14 at 12:04
1

Rookie error:

r = threading.Thread(target=receive())

I did not take the brackets off the receive():

r = threading.Thread(target=receive)
Jonathan Davies
  • 882
  • 3
  • 12
  • 27