register25
Posts: 13
Joined: Tue Jan 10, 2017 8:26 am

Running two functions simultaneously via Threading

Mon Feb 06, 2017 4:17 am

Hi all. I am working on a project to playback and record audio at the same time via Python. To run these two functions simultaneously, I used the Threading function. My code are as seen below:

Code: Select all

import threading
import time

def play1():
    while time.time() < start_time:
        pass
    threading.Thread(target=playAudio).start() 
def play2():
    while time.time() < start_time:
        pass
    threading.Thread(target=recordAudio).start() 


if __name__ == "__main__":
    start_time=time.time()+1

    threading.Thread(target=play1).start()
    threading.Thread(target=play2).start()
However, when I ran the code I was met with the error as below:
Exception in thread Thread-4:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/home/pi/0206.py", line 69, in recordAudio
data = stream.read(CHUNK)
File "build/bdist.linux-armv7l/egg/pyaudio.py", line 608, in read
return pa.read_stream(self._stream, num_frames, exception_on_overflow)
IOError: [Errno -9981] Input overflowed

KeyboardInterrupt


Can anyone kindly advise me on how to proceed from here? Thanks in advance.

User avatar
bensimmo
Posts: 4152
Joined: Sun Dec 28, 2014 3:02 pm
Location: East Yorkshire

Re: Running two functions simultaneously via Threading

Mon Feb 06, 2017 7:51 am

Does each part work without threading?

Have you programmed for python2 or python3. I see it's using python2.

register25
Posts: 13
Joined: Tue Jan 10, 2017 8:26 am

Re: Running two functions simultaneously via Threading

Mon Feb 06, 2017 2:59 pm

bensimmo wrote:Does each part work without threading?

Have you programmed for python2 or python3. I see it's using python2.
Each part does work when run separately. I am programming it for python2, does it not work on python2?

User avatar
bensimmo
Posts: 4152
Joined: Sun Dec 28, 2014 3:02 pm
Location: East Yorkshire

Re: Running two functions simultaneously via Threading

Mon Feb 06, 2017 8:52 pm

I don't know. I only use Python3 myself.

But are you (it looks like to me) creating a thread within a thread ? (I'm not sure exactly how this works, just thinking aloud incase it jogs an idea)
e.d. creating a thread of play1, and the doing whatever pass is till it's the start time and then creating a thread of the playAudio ?

If you launch just the recordAudio directly in it's own thread (ignoring all the start times and playAudio) does it work ?


As a side, maybe some of the bits I've never looked at before (conditions, semaphores, locks, timers) could be used to start them at the same time ?
https://docs.python.org/2/library/threading.html


hippy
Posts: 5770
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Running two functions simultaneously via Threading

Wed May 15, 2019 6:33 pm

The threading shown looks fine to me. An odd way to go about it but I don't think it's a threading issue per se.

But it could be an issue of the playAudio thread starting before recordAudio, or having not started before recordAudio has filled its buffer.

Without any clue as to what the playAudio and recordAudio threads do, it's hard to say.

Andyroo
Posts: 4177
Joined: Sat Jun 16, 2018 12:49 am
Location: Lincs U.K.

Re: Running two functions simultaneously via Threading

Wed May 15, 2019 6:38 pm

My guess is the data has not been fully written out and the 'play' routine deletes the file...

You may also get a clash between the two time calls without adding a short delay (even 0.1 of a second would help.

I would use a queue to communicate between the two threads:

Thread 1 records audio and closes file 1
Thread 2 waits for entry on queue
Thread 1 pops 'play file 1' on the queue
Thread 2 reads file to play from queue and plays that
Thread 1 starts records file 2

etc
etc
Need Pi spray - these things are breeding in my house...

pootle
Posts: 334
Joined: Wed Sep 04, 2013 10:20 am
Location: Staffordshire
Contact: Website

Re: Running two functions simultaneously via Threading

Wed May 15, 2019 7:12 pm

Python will not execute 2 threads at exactly the same time - so if you use code like

Code: Select all

while time.time() < start_time:
        pass
that thread will completely lock out all other threads. (search Python Global Interpreter Lock if you want to know more)

If the code in you playaudio / recordaudio functions are similar, then it is likely 1 will hog the machine and the other will be left in limbo.

If the code does any i/o or calls the right sort of library than there can be parallel execution.

The fact you got a buffer overflow in the record function suggests that the recorder wasn't keeping up with the incoming data.

hippy
Posts: 5770
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Running two functions simultaneously via Threading

Thu May 16, 2019 5:36 pm

pootle wrote:
Wed May 15, 2019 7:12 pm
Python will not execute 2 threads at exactly the same time - so ... that thread will completely lock out all other threads.
This seems to work just fine running both threads under Windows and on a Pi -

Code: Select all

import threading
import time

def One():
  while True:
    pass

def Two():
  print "2"

threading.Thread(target=One).start()
time.sleep(5)
threading.Thread(target=Two).start()

Andyroo
Posts: 4177
Joined: Sat Jun 16, 2018 12:49 am
Location: Lincs U.K.

Re: Running two functions simultaneously via Threading

Thu May 16, 2019 6:15 pm

Interesting - I had assumed the pass did not do anything at all and was compiled out based on this.

Obviously the GAL is happy to switch threads as needed in this case.

If you increase the delay before starting the second thread, do you see the CPU ramp up and get the same result (no Pi handy)?
Need Pi spray - these things are breeding in my house...

User avatar
bensimmo
Posts: 4152
Joined: Sun Dec 28, 2014 3:02 pm
Location: East Yorkshire

Re: Running two functions simultaneously via Threading

Fri May 17, 2019 8:49 am

My rudimentary understanding,..
Isn't that because the GIL is release after some very short time, hence why for I/O it's fine, because there is a long delay in getting information back. It's just synchronization that isn't good.
You could use other Pythons where the GIL is not used (?) Try multiprocessing (but that more 'cores' than synchronization?)
This is all just throwing threads out incase one works.

Return to “Python”