Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Redirect stdout to a buffer

191 views
Skip to first unread message

Ecir Hana

unread,
Nov 15, 2009, 11:28:07 AM11/15/09
to
Hello,

I'm trying to write a simple Win32 app, which may run some Python
scripts. Since it is a Windows GUI app, I would like to redirect all
output (Python print, C printf, fprinf stderr, ...) to a text area
inside the app. In other words, I'm trying to log all the output from
the app (C, Python) to a window. So far, this works for C printf():

int fds[2];
_pipe(fds, 1024, O_TEXT);
_dup2(fds[1], 1);
...
and then I read from pipe's read-end and append the text to the text
area.

But when I try to run:
Py_Initialize();
PyRun_SimpleString("print 'abc'");
Py_Finalize();

I get an error:
IOError: [Errno 9] Bad file descriptor

What am I doing wrong? How to redirect standard IO, both for C and for
Python?
PS: Maybe I'm doind something wrong, but SetStdHandle() does not work
at all....

Ecir Hana

unread,
Nov 16, 2009, 12:17:52 PM11/16/09
to

Also, maybe this matters: it's on WinXP, Python 2.6 and MinGW GCC.

Gabriel Genellina

unread,
Nov 16, 2009, 1:21:10 PM11/16/09
to pytho...@python.org
En Mon, 16 Nov 2009 14:17:52 -0300, Ecir Hana <ecir...@gmail.com>
escribiᅵ:

>> I'm trying to write a simple Win32 app, which may run some Python
>> scripts. Since it is a Windows GUI app, I would like to redirect all
>> output (Python print, C printf, fprinf stderr, ...) to a text area
>> inside the app. In other words, I'm trying to log all the output from
>> the app (C, Python) to a window. So far, this works for C printf():

>> [...]


>> PS: Maybe I'm doind something wrong, but SetStdHandle() does not work
>> at all....

This worked for me:

#include <windows.h>
#include "Python.h"

int main()
{
HANDLE hReadPipe, hWritePipe;
DWORD nr, nw;
char buffer[100];

CreatePipe(
&hReadPipe,
&hWritePipe,
NULL,
1024);
SetStdHandle(STD_OUTPUT_HANDLE, hWritePipe);

Py_Initialize();
PyRun_SimpleString("print 'from Python'");
Py_Finalize();

puts("from C\n");

CloseHandle(hWritePipe);
ReadFile(hReadPipe, buffer, 19, &nr, NULL);
CloseHandle(hReadPipe);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), buffer, nr, &nw, NULL);
}

> Also, maybe this matters: it's on WinXP, Python 2.6 and MinGW GCC.

I'm using Visual Studio 2008 Express Edition.

--
Gabriel Genellina

Ecir Hana

unread,
Nov 16, 2009, 4:04:21 PM11/16/09
to
On Nov 16, 7:21 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
> En Mon, 16 Nov 2009 14:17:52 -0300, Ecir Hana <ecir.h...@gmail.com>  
> escribió:

Hi,

thanks for the reply!

However, please, could you tell me how many bytes it read here:

ReadFile(hReadPipe, buffer, 19, &nr, NULL);

because for me, it has read 0. When I run your code, it prints from
both C and Python, but it prints straight to the console, not to the
buffer. Could you also please try to add:

WriteFile(GetStdHandle(STD_ERROR_HANDLE), "----\n", 5, &nw, NULL);

before:

WriteFile(GetStdHandle(STD_ERROR_HANDLE), buffer, nr, &nw, NULL);

Does it print "----" before "from Python" and "from C" for you?
Because for me it comes afterwards (as nr is 0)...

Gabriel Genellina

unread,
Nov 17, 2009, 12:51:07 AM11/17/09
to pytho...@python.org
En Mon, 16 Nov 2009 18:04:21 -0300, Ecir Hana <ecir...@gmail.com>
escribi�:

> On Nov 16, 7:21 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
> wrote:
>> En Mon, 16 Nov 2009 14:17:52 -0300, Ecir Hana <ecir.h...@gmail.com>
>> escribi�:

>>
>> >> I'm trying to write a simple Win32 app, which may run some Python
>> >> scripts. Since it is a Windows GUI app, I would like to redirect all
>> >> output (Python print, C printf, fprinf stderr, ...) to a text area
>> >> inside the app. In other words, I'm trying to log all the output from
>> >> the app (C, Python) to a window. So far, this works for C printf():
>> >> [...]
>
> thanks for the reply!

Sorry, my earlier code was not working as I expected; I wrongly assumed
the output was being redirected but that was not the case.
The version below ("set paranoid mode on") does redirect printf(),
fwrite(stdout,...), write(1,...), WriteFile(consolehandle,...), all those
calls in C, but fails in Python with IOError: [Errno 9] Bad file
descriptor.
I'm unable to figure out *where* it fails just by reading the Python
source; one should set a breakpoint in python26.dll to see what actually
happens.

> However, please, could you tell me how many bytes it read here:
>
> ReadFile(hReadPipe, buffer, 19, &nr, NULL);

The code below now reads from the pipe everything that has been written --
except from Python :(

<code>
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include "Python.h"

int error(char* lpszText)
{
LPVOID lpMsgBuf;
DWORD lasterror = GetLastError();

FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
lasterror,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
fprintf(stderr,
"%s: error %d: %s",
lpszText, lasterror, lpMsgBuf);
LocalFree(lpMsgBuf);
return 1;
}

int main()
{
HANDLE hReadPipe, hWritePipe;
DWORD nr, nw;
char buffer[100];

int fd, i;
BOOL bResult;

if (!CreatePipe(
&hReadPipe,
&hWritePipe,
NULL,
0))
return error("cannot create pipe");
if (!SetStdHandle(STD_OUTPUT_HANDLE, hWritePipe))
return error("SetStdHandle");

// this was missing in previous version
fd = _open_osfhandle((intptr_t)hWritePipe, _O_TEXT);
if (fd==-1) return error("_open_osfhandle");
if (_dup2(fd, 1)!=0) return error("dup2");

if (!WriteFile(hWritePipe, "WriteFile(pipe)\n", 16, &nr, NULL)) return
error("WriteFile(pipe)");
if (!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "WriteFile(stdout)\n",
18, &nr, NULL)) return error("WriteFile(stdout)");
fputs("fputs from C\n", stdout);
if (fwrite("fwrite from C\n", 1, 14, stdout)!=14) return
error("fwrite!=14");
if (write(1, "write from C\n", 13)<0) return error("write");
fflush(stdout);

fprintf(stderr, "before Python\n");
Py_Initialize();
PyRun_SimpleString("import sys;sys.stdout.write('from Python\\n')\n");
Py_Finalize();

fprintf(stderr, "before flush 2\n");
fflush(stdout);

fprintf(stderr, "before close pipe w\n");
if (!CloseHandle(hWritePipe)) return error("CloseHandle(hWritePipe)");
fprintf(stderr, "before close STDOUT Handle\n");
if (!CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE))) return
error("CloseHandle(STDOUT)");
fprintf(stderr, "before read pipe\n");
// read one char at a time...
for (i = 0; i<sizeof(buffer); i++) {
bResult = ReadFile(hReadPipe, &buffer[i], 1, &nr, NULL);
if ((!bResult) || (nr==0))
break;
}
buffer[i]='\0';
fprintf(stderr, "before close pipe r\n");
if (!CloseHandle(hReadPipe)) return error("CloseHandle(hReadPipe)");
fprintf(stderr, "==========\nnread=%d\n%s\n", i, buffer);
return 0;
}
</code>


--
Gabriel Genellina

Ecir Hana

unread,
Nov 18, 2009, 8:02:10 AM11/18/09
to
On Nov 17, 6:51 am, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:

>
> The code below now reads from the pipe everything that has been written --  
> except from Python :(

Thanks a lot for the fine code! So far I don't know why it fails to
print from Python - I'll post here any news I get...

Ecir Hana

unread,
Dec 10, 2009, 9:55:20 AM12/10/09
to
I tried to replace official Python dll with the one built with MinGW
and it works. The problem is, that port is very old and so far it
seems that official support for building Python under MinGW is nowhere
near.

I really don't want to use MSVC, so if there's any other way around
this, please, let me know.

0 new messages