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

subprocess.run()触发Python全局线程限制致脚本崩溃求助

问题解答

这个问题在Windows平台的Python环境下确实有不少开发者遇到过,核心和subprocess.CREATE_NO_WINDOW标志的使用、Windows线程资源的累积回收机制直接相关。

问题根源

  • Windows系统中,当subprocess.run()指定CREATE_NO_WINDOW时,Python的subprocess模块会额外创建辅助线程处理控制台窗口的隐藏逻辑。这些线程虽会在子进程结束后终止,但Windows对线程相关资源(如线程ID、内核对象)的回收存在延迟,长期高频调用(比如每分钟一次,持续数月)会导致资源耗尽,最终触发崩溃。
  • 你观察到的每次调用创建两个线程是正常现象:一个用于执行ping任务,另一个是CREATE_NO_WINDOW带来的控制台辅助线程。

可行解决方案

1. 替换CREATE_NO_WINDOW为DETACHED_PROCESS

改用subprocess.DETACHED_PROCESS标志,它不会创建额外的控制台辅助线程,直接让子进程脱离父进程控制台:

import subprocess
import time

PING_SIZE = "1"
PING_RETRYS = "1"
while True:
    try:
        result = subprocess.run(
            ["ping", "-n", PING_RETRYS, "-l", PING_SIZE, e.ip],
            creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )
        ping_status = result.returncode == 0
    except Exception as e:
        print(e)
        break
    time.sleep(60)

2. 直接调用系统API执行ping

用ctypes调用Windows原生的icmp.dll执行ping,完全绕开subprocess的线程开销:

import ctypes
import time

class IP_OPTION_INFORMATION(ctypes.Structure):
    _fields_ = [
        ("Ttl", ctypes.c_ubyte),
        ("Tos", ctypes.c_ubyte),
        ("Flags", ctypes.c_ubyte),
        ("OptionsSize", ctypes.c_ubyte),
        ("OptionsData", ctypes.c_char_p)
    ]

class ICMP_ECHO_REPLY(ctypes.Structure):
    _fields_ = [
        ("Address", ctypes.c_ulong),
        ("Status", ctypes.c_ulong),
        ("RoundTripTime", ctypes.c_ulong),
        ("DataSize", ctypes.c_ushort),
        ("Reserved", ctypes.c_ushort),
        ("Data", ctypes.c_char_p),
        ("Options", IP_OPTION_INFORMATION)
    ]

icmp = ctypes.WinDLL("icmp.dll")
handle = icmp.IcmpCreateFile()

PING_SIZE = 1
PING_RETRYS = 1
while True:
    try:
        ip_addr = ctypes.inet_addr(e.ip.encode('utf-8'))
        send_buf = b' ' * PING_SIZE
        reply_buf = ctypes.create_string_buffer(ctypes.sizeof(ICMP_ECHO_REPLY) + PING_SIZE)
        reply_len = ctypes.c_ulong(ctypes.sizeof(reply_buf))
        
        status = icmp.IcmpSendEcho(
            handle,
            ip_addr,
            send_buf,
            PING_SIZE,
            None,
            reply_buf,
            reply_len,
            1000  # 超时时间(毫秒)
        )
        ping_status = status > 0
    except Exception as e:
        print(e)
        break
    time.sleep(60)

icmp.IcmpCloseHandle(handle)

3. 定期释放资源

如果业务允许,可以适当延长ping间隔,或者在累计一定调用次数后自动重启脚本,清空累积的系统资源。

总结

这类属于Windows平台特有的subprocess线程资源累积问题,已经有不少开发者在长期运行的定时任务场景中遇到过,上述方案都能有效缓解或解决崩溃问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 07:42:40