为什么 os.path.exists() 阻止 Windows 命名管道连接? [英] Why does os.path.exists() stop windows named pipes from connecting?
问题描述
似乎通过使用 os.path.exists()
成功测试了一个名为管道的窗口是否存在会阻止管道工作.为什么会这样?
It seems that a successful test of the existence of a windows named pipe by using os.path.exists()
prevents the pipe from working. Why would this be?
这是成功运行的 Windows 命名管道代码:
Here is successfully working windows named-pipe code:
import time
import multiprocessing as mp
import win32pipe, win32file
PIPENAME = r'\\.\pipe\Foo'
def producer(pipe_name: str):
print('producer')
# if not os.path.exists(pipe_name):
# print(f'No pipe {pipe_name}')
# return
pipe = win32file.CreateFile(pipe_name,
win32file.GENERIC_READ | win32file.GENERIC_WRITE, # dwDesiredAccess
0, # dwShareMode
None, # lpSecurityAttributes
win32file.OPEN_EXISTING, # dwCreationDisposition
0, # dwFlagsAndAttributes
None
)
win32pipe.SetNamedPipeHandleState(pipe, win32pipe.PIPE_READMODE_MESSAGE, None, None)
win32file.WriteFile(pipe, b'foobar')
def receiver(pipe_name: str):
print('receiver')
pipe = win32pipe.CreateNamedPipe(pipe_name,
win32pipe.PIPE_ACCESS_DUPLEX,
win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT,
1, # nMaxInstances
65536, # nOutBufferSize
65536, # nInBufferSize
0, # 50ms timeout (the default)
None) # securityAttributes
win32pipe.ConnectNamedPipe(pipe)
msg = win32file.ReadFile(pipe, 65536)
print(f'msg: {msg}')
if __name__ == '__main__':
recv_p = mp.Process(target=receiver, args=(PIPENAME,))
prod_p = mp.Process(target=producer, args=(PIPENAME,))
recv_p.start()
time.sleep(0.1)
prod_p.start()
prod_p.join()
recv_p.join()
这按预期工作,接收者打印收到的消息.
This works as expected, with the receiver printing the received message.
但是如果生产者中的三个注释掉的行没有被注释,os.path.exists(pipe_name)
调用会以某种方式破坏管道,因此输出变成:
But if the three commented-out lines in the producer are uncommented, the os.path.exists(pipe_name)
call somehow breaks the pipe so the output becomes:
receiver
producer
Process Process-2:
Process Process-1:
Traceback (most recent call last):
File "C:\Users\redacted\AppData\Local\Programs\Python\Python37\lib\multiprocessing\process.py", line 297, in _bootstrap
self.run()
File "C:\Users\redacted\AppData\Local\Programs\Python\Python37\lib\multiprocessing\process.py", line 99, in run
self._target(*self._args, **self._kwargs)
File "C:\git\redacted\named_pipe_mqtt_test.py", line 18, in producer
None
pywintypes.error: (231, 'CreateFile', 'All pipe instances are busy.')
Traceback (most recent call last):
File "C:\Users\redacted\AppData\Local\Programs\Python\Python37\lib\multiprocessing\process.py", line 297, in _bootstrap
self.run()
File "C:\Users\redacted\AppData\Local\Programs\Python\Python37\lib\multiprocessing\process.py", line 99, in run
self._target(*self._args, **self._kwargs)
File "C:\git\redacted\named_pipe_mqtt_test.py", line 35, in receiver
msg = win32file.ReadFile(pipe, 65536)
pywintypes.error: (109, 'ReadFile', 'The pipe has been ended.')
为什么 os.path.exists
会破坏命名管道的窗口?
Why would os.path.exists
break windows named pipes?
我已经排除了 python 多处理库.我在 os.path.exists
之后尝试了延迟.
I've ruled out the python multiprocessing library. I've tried a delay after os.path.exists
.
这对我来说不是阻塞问题,但我很好奇.
This is not a blocking problem for me, but I am curious.
推荐答案
os.path.exists
委托给 os.stat
,在 Windows 上,os.stat
尝试打开 文件:
os.path.exists
delegates to os.stat
, and on Windows, os.stat
tries to open the file:
hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
然后它关闭文件.此时客户端无法重新打开管道,除非服务器端首先调用 DisconnectNamedPipe
,这在这段代码中不会发生.此外,当服务器端尝试从管道读取时,它正在从 os.stat
的连接尝试中读取,这会关闭管道而不写入任何数据.
Then it closes the file. At this point, the client can't reopen the pipe unless the server side first calls DisconnectNamedPipe
, which doesn't happen in this code. Also, when the server side tries to read from the pipe, it's reading from os.stat
's connection attempt, which closed the pipe without writing any data.
我认为这是一个错误.os.stat
不应该有这样的副作用.
I would consider this a bug. os.stat
should not have such side effects.
这篇关于为什么 os.path.exists() 阻止 Windows 命名管道连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!