简体   繁体   中英

How to implement threading to run two bash shell commands in python?

I have to record a wav file and at the same time I have to analyze it with sox. I am using fifo type file for this operation.

So here I need to start 2 threads at the same time but even if I use the threads I am not able to achieve what I wanna do. Always one executing first and then the other. I want them to be in parallel so that I can do some stuff.

#this should be in one thread
def test_wav(self):
    """ analyze the data """
    bashCommand = "sox {} -n stat".format(self.__rawfile)
    while self.__rec_thread.is_alive():
        process = subprocess.Popen(bashCommand.split(),stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        wav_output = process.communicate()[1] #sox outputs the details in stderr
        #do something and return

#this should be in another thread
def record_wav(self):
    bashCommand = "arecord -d 10 -c 2 -r 48000 -f S32_LE > {}".format(self.__rawfile)
    pid = subprocess.Popen(bashCommand.split())
    pid.wait()
    if pid.returncode != 0:
        raise RecordException("Failed while recording with error {}".format(pid.returncode))

I tried the following code to make them threads but failed(Always one executing first and then the other. I want them to be in parallel so that I can do some stuff). imported from threading import Thread

self.__rec_thread = Thread(target = self.record_wav())
amp_thread = Thread(target = self.test_wav())
self.__rec_thread.start()
amp_thread.start()

EDIT: First its executing the record(it minimum takes 10 sec because of the option -d 10) function completely and then the test wav function. Its like calling them one after another.

... target = self.record_wav() ...

is calling record_wav() : it executes immediately, and the program doesn't proceed until record_wav() completes. You almost always want to pass a function (or method) object to target= , almost never the result of executing the function/method. So just lose the parentheses:

... target = self.record_wav ...

if you probably use python3, you can use asyncio to run the shell command in goroutines way.

import asyncio
import sys

async def execute(command, cwd=None, shell=True):
    process = await asyncio.create_subprocess_exec(*command,
                                                   stdout=asyncio.subprocess.PIPE,
                                                   stderr=asyncio.subprocess.PIPE,
                                                   cwd=cwd,
                                                   shell=shell)
    std_out, std_err = await process.communicate()

    error = std_err.decode().strip()
    result = std_out.decode().strip()
    print(result)
    print(error)
    return result


if sys.platform == "win32":
    loop = asyncio.ProactorEventLoop()
    asyncio.set_event_loop(loop)
else:
    loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(
        asyncio.gather(execute(["bash", "-c", "echo hello && sleep 2"]), execute(["bash", "-c", "echo ok && sleep 1"])))
except Exception as e:
    raise e
finally:
    loop.close()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM