我使用一个导入C共享库的python库,该库会在stdout上打印信息。我希望获得整洁的输出以便将其通过管道使用或重定向到文件中。这些打印操作是在共享库之外完成的。
一开始,我的处理方式是:
# file: test.py
import os
from ctypes import *
from tempfile import mktemp
libc = CDLL("libc.so.6")
print # That's here on purpose, otherwise hello word is always printed
tempfile = open(mktemp(),'w')
savestdout = os.dup(1)
os.close(1)
if os.dup(tempfile.fileno()) != 1:
assert False, "couldn't redirect stdout - dup() error"
# let's pretend this is a call to my library
libc.printf("hello world\n")
os.close(1)
os.dup(savestdout)
os.close(savestdout)
这个第一种方法有一半可行: - 不知何故,在移动stdout之前需要一个“print”语句,否则始终会打印hello word。结果,它将打印一个空行,而不是库通常输出的所有模糊内容。 - 更令人恼火的是,当重定向到文件时,它会失败:
$python test.py > foo && cat foo
hello world
我第二次尝试使用Python是受到评论区中给出的另一个类似主题的启发:
import os
import sys
from ctypes import *
libc = CDLL("libc.so.6")
devnull = open('/dev/null', 'w')
oldstdout = os.dup(sys.stdout.fileno())
os.dup2(devnull.fileno(), 1)
# We still pretend this is a call to my library
libc.printf("hello\n")
os.dup2(oldstdout, 1)
这个也无法阻止“hello”打印。
因为我觉得这有点低级,所以我决定完全使用ctypes。我从这个不打印任何东西的C程序中获得了灵感:
#include <stdio.h>
int main(int argc, const char *argv[]) {
char buf[20];
int saved_stdout = dup(1);
freopen("/dev/null", "w", stdout);
printf("hello\n"); // not printed
sprintf(buf, "/dev/fd/%d", saved_stdout);
freopen(buf, "w", stdout);
return 0;
}
我建立了以下例子:
from ctypes import *
libc = CDLL("libc.so.6")
saved_stdout = libc.dup(1)
stdout = libc.fdopen(1, "w")
libc.freopen("/dev/null", "w", stdout);
libc.printf("hello\n")
libc.freopen("/dev/fd/" + str(saved_stdout), "w", stdout)
即使在printf之后,我libc.fflush(stdout)仍然会打印出“hello”。我开始觉得在Python中实现我想要的可能是不可能的。或者我获取标准输出文件指针的方式不正确。您认为呢?
sprintf
引起的,但我无法确定问题所在。 - Chinmay Kanchi