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

使用subprocess.Popen执行脚本遇OSError: [WinError 6]句柄无效问题求助

解决subprocess.Popen的WinError 6错误

问题描述

我尝试运行一个以脚本路径为参数的函数,但遇到了OSError: [WinError 6] The handle is invalid错误。已尝试添加stdin=subprocess.DEVNULL的解决方案,但仍然无效。

原函数代码

import subprocess

def run_python_script(path: str):
    
    return_value = subprocess.Popen(args=[path,], stdin=subprocess.DEVNULL)
    time.sleep(3)
    if return_value.returncode is None:
        return 1, "Script run correctly"
    else:
        return 0, f"Error occured while running script - [Errno {return_value.returncode}]"

完整错误信息

[2022-08-23 13:56:27] Exception ignored in: <function Popen.__del__ at 0x000001E32DA28B80>
Traceback (most recent call last):
  File "C:\Python\Python310\lib\subprocess.py", line 1070, in __del__
    self._internal_poll(_deadstate=_maxsize)
  File "C:\Python\Python310\lib\subprocess.py", line 1472, in _internal_poll
    if _WaitForSingleObject(self._handle, 0) == _WAIT_OBJECT_0:
OSError: [WinError 6] The handle is invalid
Exception ignored in: <function Handle.Close at 0x000001E32D7FBD90>
Traceback (most recent call last):
  File "C:\Python\Python310\lib\subprocess.py", line 199, in Close
    CloseHandle(self)
OSError: [WinError 6] The handle is invalid

问题原因

这个错误源于子进程句柄在Python垃圾回收时被重复关闭或引用失效。当Popen对象被销毁时,其__del__方法尝试轮询进程状态,但此时句柄已无效。

解决办法

修改后的代码

import subprocess
import time

def run_python_script(path: str):
    # 重定向所有标准流,避免句柄泄漏
    with subprocess.Popen(
        args=[path],
        stdin=subprocess.DEVNULL,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        shell=False
    ) as proc:
        try:
            # 等待3秒或进程结束,取先发生的
            stdout, stderr = proc.communicate(timeout=3)
            if proc.returncode == 0:
                return 1, "脚本运行正常"
            else:
                err_msg = stderr.decode('utf-8', errors='ignore').strip()
                return 0, f"脚本运行出错 - [错误码 {proc.returncode}],错误信息:{err_msg}"
        except subprocess.TimeoutExpired:
            # 超时说明进程仍在运行,清理资源后返回正常状态
            proc.kill()
            proc.communicate()
            return 1, "脚本运行正常(超时仍在运行)"

关键改进点

  • 用with语句管理Popen对象,自动释放资源,避免句柄泄漏。
  • 重定向stdout和stderr,彻底解决流句柄的无效引用问题。
  • 用communicate(timeout=3)替代time.sleep(3),更可靠地等待进程状态,同时避免进程输出阻塞。
  • 捕获超时异常,处理进程仍在运行的场景,并清理子进程资源。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 15:34:43