有一個使用包裝的解決方案(如鏈接Vinay中所述),該解決方案通過Windows 開始命令在新的控制檯窗口中啓動。
碼包裝的:
#demo.py
import signal, sys, time
def signal_handler(signal, frame):
print 'Ctrl+C received in demo.py'
time.sleep(1)
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
print 'demo.py started'
#signal.pause() # does not work under Windows
while(True):
time.sleep(1)
啓動包裝例如像:
PythonPrompt> import subprocess
PythonPrompt> subprocess.Popen("start python wrapper.py", shell=True)
您需要添加一些
#wrapper.py
import subprocess, time, signal, sys, os
def signal_handler(signal, frame):
time.sleep(1)
print 'Ctrl+C received in wrapper.py'
signal.signal(signal.SIGINT, signal_handler)
print "wrapper.py started"
subprocess.Popen("python demo.py")
time.sleep(3) #Replace with your IPC code here, which waits on a fire CTRL-C request
os.kill(signal.CTRL_C_EVENT, 0)
程序捕獲CTRL-C的代碼IPC代碼,它允許您控制封裝器觸發os.kill(signal.CTRL_C_EVENT,0)命令。我在我的應用程序中爲此使用了套接字。
說明:
Preinformation
send_signal(CTRL_C_EVENT)
不起作用,因爲CTRL_C_EVENT
僅供os.kill
。 [REF1]
os.kill(CTRL_C_EVENT)
將信號發送到在當前cmd窗口[REF2]
Popen(..., creationflags=CREATE_NEW_PROCESS_GROUP)
運行,因爲CTRL_C_EVENT
爲進程組忽略不工作的所有進程。[REF2] 這是Python文檔[REF3]
實施的解決方案中的錯誤
- 讓與Windows外殼程序指令以不同的cmd窗口程序運行開始。
- 在控件應用程序和應該獲得CTRL-C信號的應用程序之間添加一個CTRL-C請求包裝器。包裝器將運行在與獲得CTRL-C信號的應用程序相同的cmd窗口中。
- 包裝程序將自行關閉程序,該程序應該通過在cmd窗口中發送CTRL_C_EVENT的所有進程來獲得CTRL-C信號。
- 控制程序應該能夠請求包裝發送CTRL-C信號。這可以通過IPC手段來實現,例如,插座。
有用的帖子是:
我不得不刪除HTTP中的鏈接的前面,因爲我是一個新用戶,並不得張貼兩個以上的鏈路。
更新:基於IPC的CTRL-C包裝
在這裏你可以找到一個自寫的python模塊,提供一個CTRL-C環繞包括一個基於套接字的IPC。 語法與子流程模塊非常相似。
用法:
>>> import winctrlc
>>> p1 = winctrlc.Popen("python demo.py")
>>> p2 = winctrlc.Popen("python demo.py")
>>> p3 = winctrlc.Popen("python demo.py")
>>> p2.send_ctrl_c()
>>> p1.send_ctrl_c()
>>> p3.send_ctrl_c()
代碼
import socket
import subprocess
import time
import random
import signal, os, sys
class Popen:
_port = random.randint(10000, 50000)
_connection = ''
def _start_ctrl_c_wrapper(self, cmd):
cmd_str = "start \"\" python winctrlc.py "+"\""+cmd+"\""+" "+str(self._port)
subprocess.Popen(cmd_str, shell=True)
def _create_connection(self):
self._connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._connection.connect(('localhost', self._port))
def send_ctrl_c(self):
self._connection.send(Wrapper.TERMINATION_REQ)
self._connection.close()
def __init__(self, cmd):
self._start_ctrl_c_wrapper(cmd)
self._create_connection()
class Wrapper:
TERMINATION_REQ = "Terminate with CTRL-C"
def _create_connection(self, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', port))
s.listen(1)
conn, addr = s.accept()
return conn
def _wait_on_ctrl_c_request(self, conn):
while True:
data = conn.recv(1024)
if data == self.TERMINATION_REQ:
ctrl_c_received = True
break
else:
ctrl_c_received = False
return ctrl_c_received
def _cleanup_and_fire_ctrl_c(self, conn):
conn.close()
os.kill(signal.CTRL_C_EVENT, 0)
def _signal_handler(self, signal, frame):
time.sleep(1)
sys.exit(0)
def __init__(self, cmd, port):
signal.signal(signal.SIGINT, self._signal_handler)
subprocess.Popen(cmd)
conn = self._create_connection(port)
ctrl_c_req_received = self._wait_on_ctrl_c_request(conn)
if ctrl_c_req_received:
self._cleanup_and_fire_ctrl_c(conn)
else:
sys.exit(0)
if __name__ == "__main__":
command_string = sys.argv[1]
port_no = int(sys.argv[2])
Wrapper(command_string, port_no)
這可能是唯一的出路 - http://code.activestate.com/recipes/347462-terminating-a-subprocess-on-windows/用WIN32API OH或ctypes的。 – arunkumar
'subprocess.kill'將會爲我調用'TerminateProcess'就好,但不會生成^ C。我特別需要僞裝在控制檯輸入^ C的行爲。 – zwol
試試這個 - http://www.rutherfurd.net/python/sendkeys/。顯然SendKeys.SendKeys(「^ c」)應該這樣做。 – arunkumar