使用win32file.ReadFile从管道获取输出的正确方法是什么?

1 投票
3 回答
4975 浏览
提问于 2025-04-15 18:03

我正在使用 pywin32 扩展来在 Python 中访问 win32 API。对我来说,Windows 编程还是个新领域,因为我之前主要是做 POSIX 的,所以可能有些地方做得不太对。

我想正确使用 win32file.ReadFile 这个函数,但在理解可能的结果代码时遇到了一些困难。

我这样调用这个函数:

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

我正在读取我启动的一个子进程的输出。数据是好的,但我担心管道中可能有超过 4096 个字符的数据。(我更希望能做到正确,而不是随便选择一个很大的缓冲区大小。)

如果要读取的数据超过 4096 个字符,我需要多次运行 win32file.ReadFile,直到把管道中的数据读完。为了知道是否需要多次运行 ReadFile,我需要理解结果代码。

ActiveState 文档说:

结果是一个元组 (hr, string/PyOVERLAPPEDReadBuffer),其中 hr 可能是 0、ERROR_MORE_DATA 或 ERROR_IO_PENDING。

因为我在函数调用中把重叠值设置为 None,所以我觉得不需要担心 PyOVERLAPPEDReadBuffer 的问题。(而且因为我得到了有效的数据,我觉得我这样理解是对的。)

我对 hr 结果变量有两个问题:

  1. 我找不到常量 ERROR_MORE_DATA 或 ERROR_IO_PENDING 的值。
  2. ActiveState 文档似乎暗示 0 表示成功,而这些常量(不管是什么)表示失败。微软文档则说明 0 表示失败,非零表示成功,并且你需要运行 GetLastError 来获取更多信息。

那么,正确的做法是什么呢?

补充说明:我不使用 subprocess,因为我需要将子进程添加到我创建的作业对象中。目标是让所有子进程在父进程死掉时立即结束。通过将子进程添加到作业对象中,当最后一个句柄关闭时,子进程就会被终止。这个句柄由父进程持有,当父进程退出时,这个句柄会被关闭。就我所知,这一切都让我无法使用 subprocess。

3 个回答

-1

注意,ReadFile的定义是:

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

其中...

hFile = PyHANDLE

这个可以是任何Windows的句柄(可以是文件、进程、线程等...)

buffer/bufSize = PyOVERLAPPEDReadBuffer

根据文档,它会自动分配hFile的内容,无论是否有重叠。

overlapped=None [=PyOVERLAPPED]

如果你想的话,可以额外分配一个对象来存放任何超出重叠部分的数据(比如缓冲区和缓冲区大小),但默认情况下这个对象是NULL。

所以,你基本上可以像这样调用 ReadFile

ReadFile(child_stdout_r, 0, None)

你分配给它的对象将包含文件句柄的全部内容。

-1

可以考虑使用 subprocess 来启动一个新程序。这样你会得到一组像文件一样的对象,可以用来和另一个应用程序进行交流。

如果你使用的是 2.6 版本或更高版本,Popen 对象的 .terminate() 方法可以让你结束这个程序。

3

对于错误代码,可以试试 winerror.ERROR_MORE_DATAwinerror.ERROR_IO_PENDING

我对 ActiveState 文档的理解和你的一样。听起来这个封装的工作方式和原生的API有点不同。

我其实还没有尝试过这个。

撰写回答