Как правильно использовать win32file.ReadFile для получения вывода из канала? - PullRequest
1 голос
/ 15 января 2010

Я использую расширения pywin32 для доступа к Win32 API в Python. Я новичок в программировании для Windows на Python - я парень из 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 - это успех, а константы (какими бы они ни были) указывают на ошибку. Microsoft docs указывает, что 0 означает сбой, ненулевое значение означает успех, и вам нужно запустить GetLastError, чтобы узнать больше.

Как правильно это сделать?

ИЗМЕНЕНО В ДОБАВИТЬ: Я не использую подпроцесс, потому что мне нужно добавить дочерний процесс в создаваемый мной объект задания. Цель состоит в том, чтобы все дочерние процессы немедленно умирали, если родительский процесс умирает. При добавлении дочернего процесса к объекту задания дочерний процесс будет прерван, когда закроется последний дескриптор объекта задания. Дескриптор, удерживаемый родителем, будет закрыт при выходе из родителя. Все это, насколько я могу судить, не позволяет мне использовать подпроцесс.

Ответы [ 3 ]

3 голосов
/ 15 января 2010

Для кодов ошибок попробуйте winerror.ERROR_MORE_DATA и winerror.ERROR_IO_PENDING

Моя интерпретация документов ActiveState такая же, как и у вас. Похоже, что оболочка работает немного по-другому, чем нативный API. Извините, я на самом деле не пробовал это.

0 голосов
/ 28 сентября 2013

обратите внимание, что ReadFile определяется как:

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

где ...

hFile = PyHANDLE

- любой дескриптор окна (может быть файлом, процессом, потоком ...)

buffer/bufSize = PyOVERLAPPEDReadBuffer

, который согласно документации автоматически распределяет содержимое hFile независимо от того, перекрывается он или нет.

overlapped=None [=PyOVERLAPPED]

Вы можете выделить дополнительный объект для получения любых дополнительных данных, помимо перекрывающихся (buffer / bufSize), если хотите, но по умолчанию это NULL.

Итак, вы можете в основном вызывать ReadFile как:

ReadFile(child_stdout_r, 0, None)

и объект, которому вы его назначаете, будет содержать полное содержимое дескриптора файла.

0 голосов
/ 15 января 2010

Попробуйте использовать subprocess для запуска процесса. Он предоставит вам набор файловоподобных объектов, которые вы можете использовать для общения с другим приложением.

Метод .terminate() объекта Popen позволит вам завершить процесс, если вы используете 2.6 +.

...