Beantworten meiner eigenen Frage nach dem Graben für einige Zeit durch StackOverflow.
UPDATE: Dinge ändert sich dank @HarryJohnston.
Zuerst die Antwort war kein, ist es nicht möglich ist, nicht blockierende lesen auf os.pipe
auf Windows zu tun. Von this answer Ich habe das bekommt:
Der Begriff für nicht-blockierend/asynchronen E/A in Windows ‚überlappt‘ - das ist, was Sie betrachtend werden sollen.
os.pipe
unter Windows wird durch CreatePipe
API implementiert (siehe here und ... na ja, ich kann nicht os.pipe
Code in Python sources finden). CreatePipe
macht anonyme Rohre und anonymous pipes do not support asynchronous I/O.
Aber dann@HarryJohnston kommentierte, dass SetNamedPipeHandleState doc anonyme Pipe zu setzen, um nicht-blockierenden Modus ermöglicht. Ich schrieb den Test und es scheiterte mit OSError: [Errno 22] Invalid argument
. Die Fehlermeldung schien falsch, also habe ich versucht, zu überprüfen, was Ergebnis bei nicht-blockierenden Lesevorgang sein sollte, wenn Daten nicht verfügbar sind, und nach dem Lesen MSDN note on named pipe modes fand ich, dass es ERROR_NO_DATA
sein sollte, das einen Int-Wert 232 hat. Hinzufügen von ctypes.WinError()
Aufruf an Exception-Handler zeigten die erwarteten [Error 232] The pipe is being closed.
So lautet die Antwort ja ist es möglich, nicht-blockierenden zu tun auf os.pipe
unter Windows lesen, und hier ist der Beweis:
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
Siehe auch http://stackoverflow.com/questions/375427/non-blocking-read-on-a-subprocess-pipe-in-python (kein Duplikat, aber es gibt Überschneidungen). – ideasman42