我使用一个python库,它导入一个在stdout上打印的C共享库。我需要一个干净的输出,以便与管道一起使用或在文件中重定向。打印是在python之外的共享库中完成的。
一开始,我的方法是:
# 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中可能做不到我想要的事情。或者我得到一个指向stdout的文件指针的方法不正确。
你觉得呢?
将这两个答案-https://stackoverflow.com/a/5103455/1820106&;https://stackoverflow.com/a/4178672/1820106组合到上下文管理器,该上下文管理器只为其作用域阻止打印到stdout(第一个答案中的代码阻止了任何外部输出,后一个答案在结尾错过了sys.stdout.flush()):
基于@Yinon Ehrlich's answer。此变体试图避免泄漏文件描述符:
是的,你真的想用
os.dup2
代替os.dup
,就像你的第二个想法。你的代码看起来有些迂回。除了/dev/null
之外,不要乱用/dev
条目,这是不必要的。这里也没有必要用C语言写任何东西。诀窍是使用
dup
保存stdout
fde,然后将其传递给fdopen
以生成新的sys.stdout
Python对象。同时,打开一个fdes到/dev/null
,并使用dup2
覆盖现有的stdout
fdes。然后将旧FDE关闭到/dev/null
。调用dup2
是必要的,因为我们无法告诉open
我们希望它返回哪个fde,dup2
实际上是唯一的方法。编辑:如果要重定向到文件,那么stdout没有行缓冲,因此必须刷新它。您可以从Python中执行此操作,它将正确地与C进行互操作。当然,如果在向
stdout
写入任何内容之前调用此函数,则无所谓。下面是一个我刚刚测试过的在我的系统上运行的例子。
“zook”模块是C语言中非常简单的库
结果呢?
然后重定向到文件?
相关问题 更多 >
编程相关推荐