What's the correct way to use win32file.ReadFile to get output from a pipe?

I am using pywin32 extensions to access the win32 API under Python. I'm new to Windows programming in Python - I'm a POSIX guy, so I might be doing it in a bone-in manner.

I am trying to use win32file.ReadFile correctly and I am having trouble interpreting the possible result codes.

I am calling the function like this:

result, data = win32file.ReadFile(child_stdout_r, 4096, None)


I am reading the result of the child process I am running. I am getting good data, but I am concerned that there may be more data in the pipe than 4096 characters. (And I'd rather do it right, instead of just picking an arbitrarily large buffer size.)

In case more than 4096 characters are read, I will need to run win32file.ReadFile several times until I exhaust the pipe. To see if I need to run ReadFile multiple times, I need to interpret the result code.

The ActiveState docs say that:

The result is a tuple (hr, string / PyOVERLAPPEDReadBuffer), where hr can be 0, ERROR_MORE_DATA, or ERROR_IO_PENDING.

Since I am setting the overlapped value to None in the function call, I guess I don’t have to worry about any PyOVERLAPPEDReadBuffer stuff. (And since I am getting valid data, I think I am correct.)

I have two problems with the result variable hr:

  • I cannot find the values ​​for the ERROR_MORE_DATA or ERROR_IO_PENDING constants anywhere.
  • The ActiveState docs seem to imply that 0 is success and constants (no matter what they are) indicate failure. Microsoft docs indicate that 0 indicates failure, non-zero indicates success, and you need to run GetLastError to find out more.

What is the correct way to do this?

EDITED TO ADD: I am not using a subprocess because I need to add a child process to the job object that I am creating. The goal is for all child processes to die immediately if the parent process dies. By adding a child process to a job object, the child process will terminate when the last handle to the job object is closed. The handle held by the parent will be closed when the parent exits. All this, as far as I can tell, precludes the use of a subprocess.


source to share

3 answers

For error codes try winerror.ERROR_MORE_DATA and winerror.ERROR_IO_PENDING

My interpretation of the ActiveState docs is the same as yours. It looks like the wrapper works slightly differently than the native API. Sorry, I haven't actually tried this.



Consider using it subprocess

to start a process. It will give you a set of file objects that you can use to communicate with another application.

The .terminate()

Popen object method will allow you to terminate the process if you are using 2.6+.



note that ReadFile is defined as:

(int, string) = ReadFile(hFile, buffer/bufSize , overlapped)



hFile = PyHANDLE


which is any window handle (could be a file, process, stream ...)

buffer/bufSize = PyOVERLAPPEDReadBuffer


which, according to the documentation, will automatically highlight the content of the hFile regardless of whether it is overlapped or not.

overlapped=None [=PyOVERLAPPED]


you can allocate an additional object to receive any additional data beyond the overlapped (buffer / bufSize) if you want, but this is NULL by default.

So - you can basically call ReadFile like:

ReadFile(child_stdout_r, 0, None)


and the object you assigned to it will contain the complete contents of the file descriptor.



All Articles