当管道为空时,pywin32 WaitForMultipleObjects不阻塞

2024-09-28 20:54:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个只读的命名管道,并且想阻塞直到有可用的输出(与socket上的select行为相同)。在

我假设如果没有可用的输出,WaitForMultipleObjects会阻塞,但事实并非如此。为了有效地等待输出可用,可以做些什么?在

在下面的代码中,循环被执行100次,尽管PeekNamedPipe在每次迭代中返回0字节可供读取。在

import win32security, win32file, win32pipe, win32event, win32con

pipeName = r"\\.\pipe\test-pipe"

saAttr = win32security.SECURITY_ATTRIBUTES()

namedPipe = win32pipe.CreateNamedPipe(
    pipeName,
    win32con.PIPE_ACCESS_DUPLEX | win32con.FILE_FLAG_OVERLAPPED, # open mode
    win32con.PIPE_TYPE_BYTE, # pipe mode
    1, # max instances
    1, # out buffer size
    1, # in buffer size
    0, # timeout
    saAttr)

fileHandle = win32file.CreateFile(pipeName,
                                  win32file.GENERIC_READ,
                                  0, None,
                                  win32file.OPEN_EXISTING,
                                  0, None)

for i in range(100):
    # would expect this to block until data is available
    ret = win32event.WaitForMultipleObjects([fileHandle], 0, win32event.INFINITE)
    print(i, ret)
    size = 1

    buffer, bytesToRead, result = win32pipe.PeekNamedPipe(namedPipe, size)
    print(buffer, bytesToRead, result)
    if bytesToRead > 0:
        res = win32file.ReadFile(namedPipe, size)

Tags: sizebuffernamedpipepipewin32conwin32eventwin32securitywin32file
1条回答
网友
1楼 · 发布于 2024-09-28 20:54:24

我没有一种方法来生成WaitForMultipleObjects()块,但是有一种替代的非阻塞方法来检查管道中是否有数据。令人惊讶的是,win32file.GetFileSize()可以使用命名管道。Microsoft says it doesn't,但它对我有用:

import time
import win32file

pipe_path = r'\\.\pipe\asdf'

file_handle = win32file.CreateFile(pipe_path,
                                   win32file.GENERIC_READ | win32file.GENERIC_WRITE,
                                   0, None, win32file.OPEN_EXISTING, 0, None)

while True:
    if win32file.GetFileAttributes(pipe_path) != win32file.FILE_ATTRIBUTE_NORMAL:
        # pipe was closed
        break

    size = win32file.GetFileSize(file_handle)
    if size > 0:
        while size > 0:
            # pipe has data to read
            data = win32file.ReadFile(file_handle, 512)
            print('data received', data)
            size = win32file.GetFileSize(file_handle)
    else:
        time.sleep(1)

这一准则的有效性值得商榷。你可以在here中看到它。在

关于我所发现的可能是WaitForMultipleObjects()WaitForSingleObject()意外行为的原因的更多提示:

  • 希望与WaitFor*()方法一起使用的文件句柄需要具有SYNCHRONIZE访问权限(MSDN reference
    • 我不确定,但我认为这只适用于命名管道的创建者(服务器),而不是使用者(客户端)。在
    • 但这可能不是问题的根源,因为使用CreateNamedPipe()创建的文件句柄具有SYNCHRONIZE访问权限(MSDN reference
  • 我发现使用win32file.WaitFor*()python包装器方法的唯一可信任的源代码是《python Programming On Win32》(on Google Books)一书。但它们似乎在等待客户机连接,而不是数据写入管道。在

相关问题 更多 >