2017-07-04 69 views
1

我必須記錄一個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')',並檢查輸出 –

回答

1
... 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

1

如果你可能使用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()