当读取器关闭其末端而无需写入数据时,在写入器端的 Python 中检测

我的应用程序将数据流式(写入)到命名管道中,并在调用应用程序时将管道名称指定为 CLI 参数。流数据是不规则的,其中可能没有任何数据要通过管道发送。

我想检测从管道读取的另一个进程何时结束,以便快速释放我的应用程序为流分配的资源。我现在的问题是甚至检测到管道的读取端已关闭而不向管道写入任何内容。

由于流数据格式是固定的,并且不允许空写入或 ping,因此我不能简单地尝试写入一些管道数据,即使我没有任何东西可以流式传输,以便查看管道读取器是否仍在读取。

我在 Linux 上有一个可行的解决方案,不幸的是它在 Windows 上不起作用,因为 Windows 命名管道不能像在 Linux 上一样在 select() 中统一处理。在 Linux 上,我只是检查管道的写入端是否变得可读,因为这表示管道错误,然后关闭管道并释放我分配的资源。

在 Windows 上,这是不可能的。我已经打开管道进行写作:

fifo = open('//./pipe/somepipe', 'wb')

尝试fifo.read()从管道中不工作(正如预期的那样)并立即抛出一个OSException.

正如我所说,我不能尝试一些空/空写;fifo.write(b'')什么都不做,甚至根本不为可写性戳戳管道。

Windows 上有什么方法可以测试命名管道的写入端以查看读取器(客户端)是否仍然连接?


白猪掌柜的
浏览 123回答 1
1回答

郎朗坤

实际上可以WriteFile直接使用 Win32 API 编写探测零长度字节字符串:如果管道关闭,那么这将返回“不成功”(false/0),如果管道是活着,然后“成功”(真/!= 0)。正是我所要求的。因为我发现这比使用更简单,NtQueryInformationFile所以我现在使用空写方法;这是一个简化的示例:import ctypesfrom ctypes import byref, c_ulong, c_char_pimport msvcrtkernel32 = ctypes.WinDLL('kernel32', use_last_error=True)fifo = open('//./pipe/somepipe', 'wb')data = b''written = c_ulong(0)if not kernel32.WriteFile(        msvcrt.get_osfhandle(fifo.fileno()),        c_char_p(data), 0,         byref(written),         None):    last_error = ctypes.get_last_error()    if last_error in (            0x000000E8,  # ERROR_NO_DATA            # enable as required: 0x000000E9,  # ERROR_PIPE_NOT_CONNECTED    ):        # pipe broken        pass    else:        # something else is wrong...        passelse:    # pipe still okay    pass
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python