2017-01-06 21 views
1

읽기 전용 명명 된 파이프가 있고 출력이 사용 가능할 때까지 차단하고 싶습니다 (소켓에 select과 동일한 동작).pywin32 파이프가 비어있을 때 WaitForMultipleObjects가 차단되지 않습니다.

사용 가능한 출력이 없을 경우 WaitForMultipleObjects을 차단한다고 가정했지만 그렇지는 않습니다. 출력이 가능할 때까지 효율적으로 대기하기 위해 할 수있는 일은 무엇입니까? 은 모든 반복에서 읽을 수있는 0 바이트를 반환하지만 아래 코드에서 루프는 100 번 실행됩니다.

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) 

답변

0

나는 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()의 예기치 않은 동작에 대한 이유가 될 수 찾았는지에 좀 더 포인터 :

  • 파일을 사용하면 SYNCHRONIZE 액세스 권한을 갖도록 WaitFor*() 방법과 필요 사용하고자하는 핸들 (MSDN reference)
    • 잘 모르겠습니다 만, 이것은 소비자 (클라이언트)가 아닌 명명 된 파이프의 작성자 (서버)에만 적용되는 것으로 생각합니다.
    • 그러나 이것은 아마도 파일이 CreateNamedPipe()로 만든 처리하기 때문에 문제의 원인되지는 SYNCHRONIZE 액세스 권리가 나는 그게 win32file.WaitFor*() 파이썬 래퍼 방법을 사용하여 발견 된 유일한의 trustable 소스 책은
  • (MSDN reference)
  • " Python 프로그래밍 Win32에서 "( on Google Books). 그러나 그들은 파이프에 쓰여지는 데이터 대신에 클라이언트가 연결되기를 기다리는 것처럼 보입니다.