Python, C: 重定向 stdout 触发 [Errno 9]

2 投票
1 回答
1193 浏览
提问于 2025-04-15 16:06

我想记录一个用Python和C写的程序的所有输出。但是,从Python打印信息时出现了IOError: [Errno 9] Bad file descriptor的错误。

请问,有谁知道这是什么问题,怎么解决吗?

附注:我在Windows XP上,使用的是Python 2.6和MinGW GCC。

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

int main()
{
    int fds[2];
    _pipe(fds, 1024, O_BINARY);
    _dup2(fds[1], 1);
    setvbuf(stdout, NULL, _IONBF, 0);

/*  alternative version: */
//  HANDLE hReadPipe, hWritePipe; 
//  int fd;
//  DWORD nr;
//  CreatePipe(&hReadPipe, &hWritePipe, NULL, 0);
//  fd = _open_osfhandle((intptr_t)hWritePipe, _O_BINARY);
//  _dup2(fd, 1);
//  setvbuf(stdout, NULL, _IONBF, 0);

    write(1, "write\n", 6);
    printf("printf\n");
    Py_Initialize();
    PyRun_SimpleString("print 'print'"); // this breaks
    Py_Finalize();

    char buffer[1024];
    fprintf(stderr, "buffer size: %d\n", read(fds[0], buffer, 1024)); // should always be more than 0

/*  alternative version: */
//  CloseHandle(hWritePipe);
//  char buffer[1024];
//  ReadFile(hReadPipe, buffer, 1024, &nr, NULL);
//  fprintf(stderr, "buffer size: %d\n", nr); // should always be more than 0
}

1 个回答

2

我觉得这可能跟不同的C运行时有关。你知道的,不同的C运行时之间是不能传递文件描述符的。Python是用MSVC编译的(你需要查一下具体是哪个版本)。所以你可以尝试让MinGW使用相同的C运行时来编译。我记得MinGW里有一些选项可以做到这一点,比如-lmsvcrt80(或者其他合适的版本),但由于许可证的原因,他们不能分发这些库,所以你得在自己的系统上找到它们。抱歉我现在没有更多的细节,但希望这能给你一些搜索的方向。

一个更简单的方法就是全部用Python来做……只需要创建一个类,里面有一个write方法,可能还需要一个flush方法,然后把它赋值给sys.stdout。比如说对于一个文件,你可以直接传一个打开的文件对象——对你的管道做类似的事情应该也不难。然后只需导入它和sys,并在PyRun_SimpleString中设置sys.stdout。

撰写回答