在Windows上发送^ C到Python子进程对象
我有一个测试工具(用Python编写),需要通过发送^ C来关闭被测程序(用C编写)。在Unix上,
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)
通过使用Windows启动命令在新的控制台窗口中启动的包装器(如提供的Vinay链接中所述)有一个解决方案。
包装的代码: #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] 实施解决方案 >让你的程序运行在不同的cmd窗口中,Windows Shell命令启动。 有用的帖子是: 我不得不删除链接前面的http,因为我是一个新用户,不允许发布两个以上的链接。 > http://social.msdn.microsoft.com/Forums/en-US/windowsgeneraldevelopmentissues/thread/dc9586ab-1ee8-41aa-a775-cf4828ac1239/#6589714f-12a7-447e-b214-27372f31ca11 更新:基于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) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |