将 ^C 发送到 Windows 上的 Python 子进程对象

2023-12-29

I have a test harness (written in Python) that needs to shut down the program under test (written in C) by sending it ^C. On Unix,

proc.send_signal(signal.SIGINT)

工作完美。在 Windows 上,这会引发错误(“不支持信号 2”或类似的错误)。我在 Windows 上使用 Python 2.7,所以我觉得我应该可以这样做

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)

有一个解决方案是使用包装器(如 Vinay 提供的链接中所述),该包装器在 Windows 的新控制台窗口中启动start命令。

包装器的代码:

#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, 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)

您需要添加一些 IPC 代码,以允许您控制包装器触发 os.kill(signal.CTRL_C_EVENT, 0) 命令。我在我的应用程序中使用了套接字来实现此目的。

解释:

预先信息

  • send_signal(CTRL_C_EVENT)不起作用,因为CTRL_C_EVENT只为os.kill. [REF1] http://docs.python.org/library/signal.html#signal.CTRL_C_EVENT
  • os.kill(CTRL_C_EVENT)向当前cmd窗口中运行的所有进程发送信号[REF2] http://msdn.microsoft.com/en-us/library/windows/desktop/ms683155%28v=vs.85%29.aspx
  • Popen(..., creationflags=CREATE_NEW_PROCESS_GROUP)不起作用,因为CTRL_C_EVENT对于进程组将被忽略。[REF2] http://msdn.microsoft.com/en-us/library/windows/desktop/ms683155%28v=vs.85%29.aspx这是Python文档中的一个错误[REF3] http://docs.python.org/library/subprocess.html#subprocess.Popen.send_signal

实施的解决方案

  1. 让你的程序使用 Windows shell 命令在不同的 cmd 窗口中运行start.
  2. 在控制应用程序和应获取 CTRL-C 信号的应用程序之间添加 CTRL-C 请求包装器。包装器将在与应获取 CTRL-C 信号的应用程序相同的 cmd 窗口中运行。
  3. 包装器将自行关闭,并且程序将通过向 cmd 窗口中的所有进程发送 CTRL_C_EVENT 来获取 CTRL-C 信号。
  4. 控制程序应该能够请求包装器发送 CTRL-C 信号。这可以通过 IPC 方式实现,例如插座。

有用的帖子是:

我必须删除链接前面的 http,因为我是新用户,不允许发布两个以上的链接。

  • http://social.msdn.microsoft.com/Forums/en-US/windowsgeneraldevelopmentissues/thread/dc9586ab-1ee8-41aa-a775-cf4828ac1239/#6589714f-12a7-447e-b214-27372f31ca11 http://social.msdn.microsoft.com/Forums/en-US/windowsgeneraldevelopmentissues/thread/dc9586ab-1ee8-41aa-a775-cf4828ac1239/#6589714f-12a7-447e-b214-27372f31ca11
  • 我可以向 Windows 上的应用程序发送 ctrl-C (SIGINT) 吗? https://stackoverflow.com/questions/813086/can-i-send-a-ctrl-c-sigint-to-an-application-on-windows/2445728#2445728
  • 向python的子进程发送SIGINT https://stackoverflow.com/questions/1095549/sending-sigint-to-a-subprocess-of-python
  • http://bugs.python.org/issue9524 http://bugs.python.org/issue9524
  • http://ss64.com/nt/start.html http://ss64.com/nt/start.html
  • http://objectmix.com/python/387639-sending-cntrl-c.html#post1443948 http://objectmix.com/python/387639-sending-cntrl-c.html#post1443948

更新:基于 IPC 的 CTRL-C 包装器

在这里你可以找到一个自写的 python 模块,提供 CTRL-C 包装,包括基于套接字的 IPC。 语法与 subprocess 模块非常相似。

Usage:

>>> 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()

Code

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)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 ^C 发送到 Windows 上的 Python 子进程对象 的相关文章

随机推荐

  • 无法远程访问9200端口

    刚刚开始使用elasticsearch 5 4 0 首先我将其安装在Mac 本地 上 然后安装在服务器上 在 Mac 中 当我在浏览器中运行 http 本地主机 9200 http localhost 9200 它向我显示输出 name N
  • Json解析Python子进程

    这是代码 inputDomain subprocess Popen cat etc localdomains shell True stdout subprocess PIPE domains inputDomain stdout read
  • 对话框打开时布局混乱

    我面临着一个非常奇怪的错误 其中一个布局的父级是 ConstraintLayout 当对话框打开时 后面的布局会自动开始收缩和移动 请参阅随附的 gif 来了解有关该错误的信息 请检查我的代码 看看我是否做错了什么 这是我的布局
  • 如何动态设置UIScrollView的内容大小

    我有关于UIScrollview 故事是我有一个UIView名为 ChartsView 我通过重写方法自己重新绘制它drawRect 绘图的内容是动态生成的 所以直到运行时我才知道它的大小 问题是如何 在哪里可以动态设置其超级视图 scro
  • PowerShell 中是否提供联合类型

    类型化数组就像 arrIntOnly Int 1 2 3 对于确保所有元素都是有效类型很有用 但是是否可以定义多种类型 例如 arrIntOrString Int String 1 two 3 PowerShell 可以not有联合数据类型
  • 根据同一列表中的下一个项目从列表中删除项目

    我刚刚开始学习 python 这里有一个蛋白质序列的排序列表 总共 59 000 个序列 其中一些是重叠的 我在这里列出了一个玩具清单 例如 ABCDE ABCDEFG ABCDEFGH ABCDEFGHIJKLMNO CEST DBTSF
  • 针对 Android、iPhone 等集成的 .NET Web 服务格式/协议的建议

    我正在为我的 ASP NET MVC 3 网站构建一个 Web 服务 理想情况下 我希望所有客户端 我的网页 iPhone 应用程序 Android 应用程序 Windows Phone 7 应用程序等 使用相同的服务层来加载和保存数据 我
  • Ajax 重新加载后 jQuery mCustomScrollbar 消失

    like here https stackoverflow com questions 13231199 jquery mcustomscrollbar not working on ajax content 24632046 246320
  • 如何在 Cython 中创建固定长度、可变的 Python 对象数组?

    我需要有一个 python 对象数组用于创建 trie 数据结构 我需要一个像元组一样长度固定 像列表一样可变的结构 我不想使用列表 因为我希望能够确保该列表是exactly正确的大小 如果它开始分配额外的元素 随着 trie 变大 内存开
  • 使用 cxf 处理 jax-rs webservice 中的身份验证和授权

    我有一个带有jsps的网络应用程序 我没有使用任何 struts 或 mvc 框架 我们使用 Apache CXF 构建 JAX RS 服务 现在我想做以下事情 允许用户使用用户名和密码登录 对于所有后续对 Web 服务的调用 应使用相同的
  • 取消 RX.Net Observer 正在进行的 OnNext 方法

    正如我原来的问题中所述 参见将相互依赖的事件流与 RX Net 关联起来 https stackoverflow com questions 26640548 correlate interdependent event streams w
  • Objective-C:self = nil 不会将实例设置为空值

    我有下一个代码 非常简单 SecondViewController m if contentRvController nil contentRvController ContentView alloc initWithNibName Con
  • 推送通知的 iOS 设备令牌示例

    我需要通过服务器身份验证方法 该方法需要 deviceToken 进行注册 但我只有模拟器 无法从中获取令牌 并且我想向服务器发送错误令牌 例如 000 000 000 但我不知道设备令牌中有多少位 任何人都可以帮我提供示例设备令牌吗 设备
  • 我应该如何在 App Engine 上进行全文搜索?

    我应该如何做才能在 App Engine 上进行快速全文搜索 同时尽可能少地进行工作 以及尽可能少的 Java 我正在使用 Python 我在最近的一个项目中使用了 Whoosh 和 appengine 它似乎工作得很好 看一下https
  • Java 中是否存在使用泛型(域模型,而不是持久层)的多对多集合?

    我似乎在谷歌中使用了错误的搜索词 我已经为多对多关联编写了一个通用类 但我猜这已经完成了 它很可能存在于比我自己的实现更好的实现中 这是我第一次尝试编写通用类 为了更好地了解我正在寻找的内容 我添加了一些我自己的片段 我用 2 个哈希图来支
  • 月底的 Airflow DAG 调度

    我想在 Airflow v1 9 0 上运行计划 我的DAG需要在每个月底运行 但我不知道如何编写设置 my dag DAG dag id DAG ID catchup False default args default args sch
  • Java 8泛型函数应该是不明确的,但在运行时失败

    我正在尝试将 Java 7 代码迁移到 Java 8 因此我的代码类似于 package tests import java util Arrays import java util Map public class Tests priva
  • $project mongodb 聚合中的 $regex

    我有一个users具有类型的位置字段的集合String 我想沿着文档传递一个分数字段 该字段显示文档的位置是否与文本 Austin 相似 例如记录的位置是德克萨斯州奥斯汀 我希望它与Austin 我以为可以使用 regex为了这 我写了这个
  • Cloud Firestore 安全规则 - 只允许写入文档中的特定密钥

    我目前正在使用 Firestore 数据库为我的应用程序编写一些规则 目前 每个人都可以读取数据 经过身份验证的用户可以写入 match quizzes quizId allow read allow write if request au
  • 将 ^C 发送到 Windows 上的 Python 子进程对象

    I have a test harness written in Python that needs to shut down the program under test written in C by sending it C On U