proc.send_signal(signal.SIGINT)
工作完美。在Windows上,会引发错误(“不支持信号2”)。我正在使用Python 2.7 for Windows,所以我有一个印象,我应该能够做到
proc.send_signal(signal.CTRL_C_EVENT)
但这根本不做任何事情。我需要做什么?这是创建子进程的代码:
# Windows needs an extra argument passed to subprocess.Popen,# but the constant isn't defined on Unix. try: kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP except AttributeError: pass proc = subprocess.Popen(argv,stdin=open(os.path.devnull,"r"),stdout=subprocess.PIPE,stderr=subprocess.PIPE,**kwargs)
包装的代码:
#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:
#demo.py import signal,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)
您需要添加一些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]中的一个错误
实施解决方案
>让你的程序运行在不同的cmd窗口中,Windows Shell命令启动。
>在控制应用程序和应用程序之间添加一个CTRL-C请求包装器,该应用程序应该获得CTRL-C信号。包装器将与应该获得CTRL-C信号的应用程序在同一个cmd窗口中运行。
>包装器将关闭本身以及通过发送cmd窗口中的所有进程CTRL_C_EVENT来获取CTRL-C信号的程序。
>控制程序应该能够请求包装器发送CTRL-C信号。这可能通过IPC手段实现。插座。
有用的帖子是:
我不得不删除链接前面的http,因为我是一个新用户,不允许发布两个以上的链接。
> http://social.msdn.microsoft.com/Forums/en-US/windowsgeneraldevelopmentissues/thread/dc9586ab-1ee8-41aa-a775-cf4828ac1239/#6589714f-12a7-447e-b214-27372f31ca11
> Can I send a ctrl-C (SIGINT) to an application on Windows?
> Sending SIGINT to a subprocess of python
> http://bugs.python.org/issue9524
> http://ss64.com/nt/start.html
> http://objectmix.com/python/387639-sending-cntrl-c.html#post1443948
更新:基于IPC的CTRL-C Wrapper
在这里,您可以找到一个自写的python模块,提供包含基于插座的IPC的CTRL-C包装。
语法与子进程模块非常相似。
用法:
>>> 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,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)