0

我呼籲myMain.py與遞增的數字自動執行另一個Python程序這個簡單的Python腳本,我運行它在CentOS 7:Python腳本無法通過按Ctrl + C或Ctrl終止+ BREAK

#!/usr/bin/python 

import os 
import sys 
import time 

def main(): 
    step_indicator = "" 
    arrow = ">" 
    step = 2 
    try: 
     for i in range(0,360, step): 
      step_percentage = float(i)/360.0 * 100 
      if i % 10 == 0: 
       step_indicator += "=" 
      os.system("python myParsePDB.py -i BP1.pdb -c 1 -s %s" % step) 
      print("step_percentage%s%s%.2f" % (step_indicator,arrow,step_percentage)+"%") 
    except KeyboardInterrupt: 
     print("Stop me!") 
     sys.exit(0) 


if __name__ == "__main__": 
    main() 

現在我只知道這個腳本是單線程安全的,但我不能用Ctrl+C鍵盤中斷來終止它。

我看過一些相關的問題:如Cannot kill Python script with Ctrl-CStopping python using ctrl+c我意識到,Ctrl+Z不殺的過程中,它只是暫停過程,讓過程在後臺。 Ctrl+Break也適用於我的情況,我認爲它只會終止我的主線程,但會保留子進程。

我也注意到,調用os.system()會從當前執行過程產生一個子進程。同時,我也有os文件I/O功能,os.system("rm -rf legacy/*")將在myParsePDB.py中調用,這意味着這個子進程也會產生子進程。那麼,如果我想趕上Ctrl+CmyMain.py,我應該守護只有myMain.py或者我應該守護每個進程時,他們產卵?

+0

是否有必要在子進程運行'myParsePDB'?難道你不能把它寫成一個普通的模塊,你可以使用這個腳本調用而不是使用'os.system'函數嗎?你應該可以用''shutil.rmtree''來執行'rm'功能(https://docs.python.org/3/library/shutil.html#shutil.rmtree) –

+0

@ TadhgMcDonald-Jensen有必要運行'myParsePDB'。 'rm'只是'myParsePDB'中的一小部分。 –

回答

0

這是處理信號處理時可能引發的一般問題。 Python信號不是例外,它是操作系統信號的包裝。因此,python中的信號處理依賴於操作系統,硬件和許多條件。但是,如何處理這些問題是相似的。

按照本教程中,我引用下面的段落:signal – Receive notification of asynchronous system events

信號是一個操作系統的功能,提供的 通知您事件的程序的手段,有它處理 異步。它們可以由系統本身生成,或者從一個進程發送到另一個進程。由於信號會中斷程序的正常流程 ,因此如果在中間接收到信號,某些操作(特別是I/O) 可能會產生錯誤。

信號由整數標識,並在操作 系統C標頭中定義。 Python將適合於平臺的信號作爲信號模塊中的符號公開。對於以下示例,I 將使用SIGINT和SIGUSR1。兩者通常都是爲所有Unix 和類Unix系統定義的。

在我的代碼:

os.system("python myParsePDB.py -i BP1.pdb -c 1 -s %s" % step)裏面的for循環會爲一點時間來執行,並且會花一些時間在I/O文件。如果鍵盤中斷傳遞速度過快,並且在寫入文件後沒有異步捕獲,信號可能會在操作系統中被阻塞,所以我的執行仍然是for循環的try子句。 (在執行過程中檢測到的錯誤稱爲例外情況,不是無條件致命的:Python Errors and Exceptions)。

因此讓他們asynchonous最簡單的方法就是等待:

try: 
    for i in range(0,360, step): 
     os.system("python myParsePDB.py -i BP1.pdb -c 1 -s %s" % step) 
     time.sleep(0.2) 
except KeyboardInterrupt: 
    print("Stop me!") 
    sys.exit(0) 

這可能會降低性能,但它保證了信號可以等待os.system()執行後捕獲。如果需要更好的性能,您可能還想使用其他同步/異步功能來解決問題。

更多Unix的信號參考,還請查看:Linux Signal Manpage