<p>是的,你真的想用<code>os.dup2</code>代替<code>os.dup</code>,就像你的第二个想法。你的代码看起来有些迂回。除了<code>/dev/null</code>之外,不要乱用<code>/dev</code>条目,这是不必要的。这里也没有必要用C语言写任何东西。</p>
<p>诀窍是使用<code>dup</code>保存<code>stdout</code>fde,然后将其传递给<code>fdopen</code>以生成新的<code>sys.stdout</code>Python对象。同时,打开一个fdes到<code>/dev/null</code>,并使用<code>dup2</code>覆盖现有的<code>stdout</code>fdes。然后将旧FDE关闭到<code>/dev/null</code>。调用<code>dup2</code>是必要的,因为我们无法告诉<code>open</code>我们希望它返回哪个fde,<code>dup2</code>实际上是唯一的方法。</p>
<p><strong>编辑:</strong>如果要重定向到文件,那么stdout没有行缓冲,因此必须刷新它。您可以从Python中执行此操作,它将正确地与C进行互操作。当然,如果在向<code>stdout</code>写入任何内容之前调用此函数,则无所谓。</p>
<p>下面是一个我刚刚测试过的在我的系统上运行的例子。</p>
<pre><code>import zook
import os
import sys
def redirect_stdout():
print "Redirecting stdout"
sys.stdout.flush() # <--- important when redirecting to files
newstdout = os.dup(1)
devnull = os.open(os.devnull, os.O_WRONLY)
os.dup2(devnull, 1)
os.close(devnull)
sys.stdout = os.fdopen(newstdout, 'w')
zook.myfunc()
redirect_stdout()
zook.myfunc()
print "But python can still print to stdout..."
</code></pre>
<p>“zook”模块是C语言中非常简单的库</p>
<pre><code>#include <Python.h>
#include <stdio.h>
static PyObject *
myfunc(PyObject *self, PyObject *args)
{
puts("myfunc called");
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef zookMethods[] = {
{"myfunc", myfunc, METH_VARARGS, "Print a string."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
initzook(void)
{
(void)Py_InitModule("zook", zookMethods);
}
</code></pre>
<p>结果呢?</p>
<pre><code>$ python2.5 test.py
myfunc called
Redirecting stdout
But python can still print to stdout...
</code></pre>
<p>然后重定向到文件?</p>
<pre><code>$ python2.5 test.py > test.txt
$ cat test.txt
myfunc called
Redirecting stdout
But python can still print to stdout...
</code></pre>