如何在 python 中对 运行 两个 bash shell 命令执行线程化?
How to implement threading to run two bash shell commands in python?
我要录制一个wav文件,同时还要用sox解析。我正在为此操作使用 fifo 类型文件。
所以这里我需要同时启动 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()
编辑:首先它完全执行记录(由于选项 -d 10,它至少需要 10 秒)功能,然后是测试 wav 功能。就像一个接一个地叫他们。
... target = self.record_wav() ...
是调用 record_wav()
:它立即执行,直到record_wav()
完成后程序才会继续。您几乎总是想将函数(或方法)对象传递给 target=
,几乎从不传递执行 function/method 的结果。所以去掉括号:
... target = self.record_wav ...
如果你可能使用 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()
我要录制一个wav文件,同时还要用sox解析。我正在为此操作使用 fifo 类型文件。
所以这里我需要同时启动 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()
编辑:首先它完全执行记录(由于选项 -d 10,它至少需要 10 秒)功能,然后是测试 wav 功能。就像一个接一个地叫他们。
... target = self.record_wav() ...
是调用 record_wav()
:它立即执行,直到record_wav()
完成后程序才会继续。您几乎总是想将函数(或方法)对象传递给 target=
,几乎从不传递执行 function/method 的结果。所以去掉括号:
... target = self.record_wav ...
如果你可能使用 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()