Jonathan Davies
Jonathan Davies

Reputation: 884

Run function in background and continue with program

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.

Upvotes: 1

Views: 7900

Answers (2)

Peter Sutton
Peter Sutton

Reputation: 1223

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()

Upvotes: 1

Jonathan Davies
Jonathan Davies

Reputation: 884

Rookie error:

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

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

r = threading.Thread(target=receive)

Upvotes: 1

Related Questions