gpt4 book ai didi

python - Windows 上的 os.pipe 非阻塞读取

转载 作者:太空狗 更新时间:2023-10-29 20:18:19 26 4
gpt4 key购买 nike

这个问题- How to read from an os.pipe() without getting blocked? - 展示了如何检查 os.pipe 是否有任何 Linux 数据的解决方案,为此您需要将管道置于非阻塞模式:

import os, fcntl
fcntl.fcntl(thePipe, fcntl.F_SETFL, os.O_NONBLOCK)

在 Windows 上我们有这个:

ImportError: No module named fcntl

但是 os.pipe 在那里:

>>> os.pipe()
(3, 4)

那么,是否可以在 Windows 上进行非阻塞读取或查看 os.pipe 的内容?

最佳答案

在通过 StackOverflow 挖掘一段时间后回答我自己的问题。

更新:感谢@HarryJohnston,事情发生了变化。

起初答案是,在Windows 上不可能在os.pipe 上进行非阻塞读取。来自 this answer我明白了:

The term for non-blocking / asynchronous I/O in Windows is 'overlapped' - that's what you should be looking at.

Windows 上的

os.pipe 是通过 CreatePipe API 实现的(请参阅 here 以及……好吧,我找不到 os.pipe Python sources 中的代码)。 CreatePipe 创建匿名管道,anonymous pipes do not support asynchronous I/O .

然后 @HarryJohnston评论说SetNamedPipeHandleState doc 允许将匿名管道置于非阻塞模式。我编写了测试,但它因 OSError: [Errno 22] Invalid argument 而失败。错误消息似乎是错误的,所以我尝试检查当数据不可用时非阻塞读取操作的返回结果应该是什么,并在阅读后 MSDN note on named pipe modes我发现它应该是 ERROR_NO_DATA,它的 int 值为 232。将 ctypes.WinError() 调用添加到异常处理程序显示了预期的 [Error 232] 管道正在关闭。

所以,答案是是的,在 Windows 上可以在 os.pipe 上进行非阻塞读取,这是证明:

import msvcrt
import os

from ctypes import windll, byref, wintypes, GetLastError, WinError
from ctypes.wintypes import HANDLE, DWORD, POINTER, BOOL

LPDWORD = POINTER(DWORD)

PIPE_NOWAIT = wintypes.DWORD(0x00000001)

ERROR_NO_DATA = 232

def pipe_no_wait(pipefd):
""" pipefd is a integer as returned by os.pipe """

SetNamedPipeHandleState = windll.kernel32.SetNamedPipeHandleState
SetNamedPipeHandleState.argtypes = [HANDLE, LPDWORD, LPDWORD, LPDWORD]
SetNamedPipeHandleState.restype = BOOL

h = msvcrt.get_osfhandle(pipefd)

res = windll.kernel32.SetNamedPipeHandleState(h, byref(PIPE_NOWAIT), None, None)
if res == 0:
print(WinError())
return False
return True


if __name__ == '__main__':
# CreatePipe
r, w = os.pipe()

pipe_no_wait(r)

print os.write(w, 'xxx')
print os.read(r, 1024)
try:
print os.write(w, 'yyy')
print os.read(r, 1024)
print os.read(r, 1024)
except OSError as e:
print dir(e), e.errno, GetLastError()
print(WinError())
if GetLastError() != ERROR_NO_DATA:
raise

关于python - Windows 上的 os.pipe 非阻塞读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34504970/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com