如何实现线程在python中运行两个bash shell命令?

问题描述:

我必须记录一个wav文件,同时我必须用sox来分析它。我正在使用fifo类型文件进行此操作。如何实现线程在python中运行两个bash shell命令?

因此,我需要在同一时间启动2个线程,但即使使用线程,我也无法实现我想要做的事情。总是先执行一个,然后执行另一个。我希望他们平行,以便我可以做一些事情。

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

我尝试下面的代码,使他们线程但是失败了(总是一个第一,然后其他执行。我希望他们能在并行,这样我可以做一些东西)。 进口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() 

编辑:首先其执行记录完全,然后(它最小花费,因为该选项的10秒-d 10)功能的测试的wav功能。就像是一个接一个地给他们打电话。

+0

你是什么意思失败?描述输出或错误 –

+0

@OferSadan总是先执行一个,然后执行另一个。我希望他们平行,以便我可以做一些事情。 – AQU

+0

我不知道'sox'命令的作用是什么,但是可能它运行得太快而不管它是否有线程?在每个函数的顶部添加一个print('thread 1 started')',并检查输出 –

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

调用record_wav():立即执行,并且该程序不会继续,直到record_wav()完成。您几乎总是希望将函数(或方法)对象传递给target=,几乎从不会执行函数/方法的结果。所以就丢掉括号:

... target = self.record_wav ... 
+1

这里有一点疑问,我没有在任何文档中发现。你能指出它吗? – AQU

+1

'f()'总是调用'f' - 上下文完全不相关。如果您对例如'x = f()'语句调用'f'并不感到惊讶,那么您应该同样不会感到惊讶,'target = f()'也调用'f'。 'Thread'文档显然确实说'* target *是要由run()方法调用的可调用对象。 'self.record_wav'是一个可调用的对象。 'self.record_wav()'就是'self.record_wav()'_returns_。 –

+0

看来我醉了:P现在我明白了。这是编程的基础。我不知道我的愚蠢的大脑错过了解它。 – AQU

如果你可能使用python3,你可以使用asyncio以goroutines方式运行shell命令。

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