You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python.NET 3.0.0下C#控制台程序Ctrl+C无法触发问题求助

问题描述

我使用Python.NET 3.0.0从C#控制台程序中执行Python脚本,核心代码如下:

执行Python脚本的代码

public void executePy {
      using (Py.GIL())
                {
                    var pythonThreadID = PythonEngine.GetPythonThreadID();
                    _pythonThreadIds.Add(pythonThreadID);
                    var scope = Py.CreateScope();
                    var file = PythonEngine.Compile(fileContent);
                    scope.Execute(file);

                    dynamic mod = scope.Get("data");


                    mod(abc);
                } }

上述代码每60秒循环运行一次。

中断Python线程的代码

public async stopThreads()
{ if (_pythonThreadIds.Count > 0)
        {
            foreach (var id in _pythonThreadIds)
            {
                using (Py.GIL())
                {
                    PythonEngine.Interrupt(id);
                }

            }
            PythonEngine.EndAllowThreads(_state);

            PythonEngine.Shutdown();
        } }

基类触发停止的代码

public async Task StopThreadClasses()
    {
        try
        {
            // cancel all running processes
            _cts.Cancel();

            foreach (ITB obj in _commandBaseClasses)
            {
                await obj.Stop();
            }

        }
        catch (Exception ex)
        {
            //log_message
        }
        finally
        {
            _cts.Dispose();
        }
    }

问题现象:当控制台程序循环执行executePy代码时,Ctrl+C无法被程序识别;仅运行C#代码、未触发Python线程时,Ctrl+C可正常识别并终止线程。每个类的StopThreads函数会在用户按下Ctrl+C时触发,但当前场景下未生效。

排查建议
  • 检查GIL持有对信号处理的阻塞:Python的GIL会阻塞操作系统信号(包括Ctrl+C触发的SIGINT),如果executePy中mod(abc)执行耗时久且持续持有GIL,会导致C#主线程无法及时响应Ctrl+C。建议将Python执行逻辑改为非阻塞调用,或者在Python脚本中添加信号捕获逻辑,定期检查中断标志。
  • 验证PythonEngine.Interrupt的有效性:Interrupt需要目标Python线程处于可中断状态(比如执行Python字节码的间隙),如果mod(abc)是纯原生扩展调用(无Python字节码执行),Interrupt可能失效。可以在Python脚本中插入time.sleep(0.1)这类会释放GIL的操作,让线程有机会响应中断。
  • 确认_state变量的正确性:PythonEngine.EndAllowThreads(_state)中的_state必须是BeginAllowThreads返回的有效状态对象,若未正确初始化或已释放,会导致该行代码失效,甚至引发异常阻止后续Shutdown执行。
  • 检查Ctrl+C信号处理优先级:C#控制台的Ctrl+C信号处理可能被Python的信号逻辑覆盖,可在C#代码中显式注册Console.CancelKeyPress事件,确保事件处理程序优先获取控制权,比如在处理逻辑中先强制终止Python线程,再执行后续停止操作。
  • 排查_pythonThreadIds的准确性:确保每次执行executePy时添加的线程ID是当前活跃的Python线程ID,无重复添加或未移除已结束的线程ID。若线程ID无效,Interrupt调用不会产生效果。
  • 验证异步停止逻辑的等待有效性:stopThreads是异步函数,需确认基类StopThreadClasses中await obj.Stop()确实等待了stopThreads执行完成,避免因未等待导致中断操作不彻底。
  • 调整PythonEngine.Shutdown的执行时机:Shutdown会彻底关闭Python引擎,需确保所有Python线程已被中断并退出后再调用,否则可能导致资源泄漏或阻塞。

内容的提问来源于stack exchange,提问作者qwerty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 18:33:28