2017-04-11 72 views
8

我有攪拌器Python腳本,其中有Python的subprocess.call不等待進程結束攪拌機

subprocess.call(os.path.abspath('D:/Test/run-my-script.sh'),shell=True)

其次是取決於這個shell腳本來完成許多其他的代碼。會發生什麼,它不會等待它完成,我不知道爲什麼?我甚至用Popen代替call試圖如圖所示:

p1 = subprocess.Popen(os.path.abspath('D:/Test/run-my-script.sh'),shell=True) 
p1.wait() 

,我嘗試使用commuincate,但它仍然沒有奏效:

p1 = subprocess.Popen(os.path.abspath('D:/Test/run-my-script.sh'),shell=True).communicate() 

這個shell腳本在Mac OS的偉大工程(轉換路後)並在使用時等待subprocess.call(['sh', '/userA/Test/run-my-script.sh'])

但在Windows上這是發生了什麼,我在Blender中運行下面的python腳本,然後一旦它進入子進程行Git bash打開並運行shell腳本,而攪拌機不等待它完成它只是在其控制檯打印Hello而無需等待Git Bash完成。任何幫助?

import bpy 
import subprocess 
subprocess.call(os.path.abspath('D:/Test/run-my-script.sh'),shell=True) 
print('Hello') 
+1

,當你運行'在Windows上會發生什麼d:/測試/運行我的-script.sh'命令行?它是否立即返回? – AShelly

+0

你可以發佈bash腳本嗎? –

回答

3

subprocess.run將默認等待進程結束。

+0

但我的情況下,它不會等待,這就是爲什麼我問... – Tak

+0

您的問題給了我你使用'subprocess.Popen'的inpression而不是'subprocess.run'它不等待使用運行? – Grr

+0

我使用了subprocess.run,但它並沒有等待 – Tak

4

您可以使用subprocess.call來做到這一點。

子過程。 呼叫指定參數時,*,標準輸入=無,標準輸出=無,標準錯誤=無,殼=假,超時=無

運行由ARGS中描述的命令。等待命令完成,然後返回returncode屬性。

編輯:我覺得我有什麼事情預感。該命令適用於Mac,因爲Mac相信支持Bash開箱即用(至少在功能上等同於),而在Windows上它看到您嘗試運行「.sh」文件,而是激發了Git Bash,假設開始時執行一對分叉。

因爲這個Python 認爲你的腳本已經完成,所以PID不見了。

如果我是你,我會做到這一點:

  • 使用tempfile模塊生成一個唯一的,不存在的,絕對在你的「啓動」腳本路徑。
  • 啓動腳本時,請將您剛纔創建的路徑作爲參數傳遞。
  • 當腳本啓動時,讓它在路徑上創建一個文件。完成後,刪除文件。
  • 啓動腳本應監視該文件的創建和刪除以指示腳本的狀態。

希望這是有道理的。

+0

有些情況下,這不起作用。 以我爲例,該過程是一個程序,它創建一個文件,然後訪問該文件以修改其內容一段時間。當程序仍在修改文件的內容並且進程仍在進行時,子進程調用將該進程視爲已完成,當文件被創建時。任何解決方法可用? – SeF

+0

@SeF然後,你正在做一些意想不到的事情 - 文檔非常明確地說明了函數的工作原理。也許你正在分叉或執行到另一個進程? – joeb

2

您可以使用os.system,像這樣:

import bpy 
import os 
os.system("sh "+os.path.abspath('D:/Test/run-my-script.sh')) 
print('Hello') 
2

使用subprocess.PopenPopen.wait

process = subprocess.Popen(['D:/Test/run-my-script.sh'],shell=True, executable="/bin/bash") 
process.wait() 

你也可以使用check_call()代替POPEN。

4

您可以使用Popen.communicate API。

p1 = subprocess.Popen(os.path.abspath('D:/Test/run-my-script.sh'),shell=True) 
sStdout, sStdErr = p1.communicate() 

命令

Popen.communicate(input=None, timeout=None) 

互動與過程:發送數據到標準輸入。從stdout和stderr中讀取數據,直到達到文件結尾。等待進程終止。

+0

感謝所有參與賞金的人士,這個答案提出了一個等待命令的替代方案,它似乎並不是一直都在工作。 – SeF

0

顯然有運行命令失敗的情況。 這是我的解決方法:

def check_has_finished(pfi, interval=1, timeout=100): 
    if os.path.exists(pfi): 
     if pfi.endswith('.nii.gz'): 
      mustend = time.time() + timeout 
      while time.time() < mustend: 
       try: 
        # Command is an ad hoc one to check if the process has finished. 
        subprocess.check_output('command {}'.format(pfi), shell=True) 
       except subprocess.CalledProcessError: 
        print "Caught CalledProcessError" 
       else: 
        return True 
       time.sleep(interval) 
      msg = 'command {0} not working after {1} tests. \n'.format(pfi, timeout) 
      raise IOError(msg) 
     else: 
      return True 
    else: 
     msg = '{} does not exist!'.format(pfi) 
     raise IOError(msg)