从python模块我调用一个 Hello World 可执行文件,它只是将Hello World
打印到stdout。我有兴趣将该输出重定向到python StringIO
并进入this回答,这几乎让我一直都能找到解决方案。
这个答案的关键部分是这段代码:
1. def redirect_stdout():
2. print "Redirecting stdout"
3. sys.stdout.flush() # <--- important when redirecting to files
4. newstdout = os.dup(1)
5. devnull = os.open('/dev/null', os.O_WRONLY)
6. os.dup2(devnull, 1)
7. os.close(devnull)
8. sys.stdout = os.fdopen(newstdout, 'w')
此外,我想恢复重定向之前的stdout。
dup
和dup2
在做什么?/dev/null
?sys.stdout = os.fdopen(newstdout, 'w')
)StringIO
对象中?我很确定,一旦我得到问题1的答案,问题2和3的答案就很容易了。无论如何,我决定发布它们,或许将问题1的答案推到我想去的方向。
答案 0 :(得分:11)
我在下面写了一些额外的评论,这些评论应该更清楚redirect_stdout
函数中的内容:
def redirect_stdout():
print "Redirecting stdout"
sys.stdout.flush() # <--- important when redirecting to files
# Duplicate stdout (file descriptor 1)
# to a different file descriptor number
newstdout = os.dup(1)
# /dev/null is used just to discard what is being printed
devnull = os.open('/dev/null', os.O_WRONLY)
# Duplicate the file descriptor for /dev/null
# and overwrite the value for stdout (file descriptor 1)
os.dup2(devnull, 1)
# Close devnull after duplication (no longer needed)
os.close(devnull)
# Use the original stdout to still be able
# to print to stdout within python
sys.stdout = os.fdopen(newstdout, 'w')
需要注意的一件重要事情是,一个进程在启动时从操作系统获得三个不同的file descriptors:
正如评论中所解释的,上面的代码利用stdout的文件描述符和文件描述符复制函数来使C代码使用不同的stdout,同时仍然在python代码中保留对原始stdout的引用能够打印。
答案 1 :(得分:7)
/dev/null
是一个特殊的设备文件(UNIX中的所有内容都是一个文件!),它吞下了写入黑洞的所有内容。 dup
复制文件描述符。如果您习惯使用Windows,UNIX中的文件描述符是一个特殊的整数,表示一个打开的文件,它就像一个Windows文件句柄。
程序正在打开/dev/null
进行写入(仅),获取它的文件描述符的副本,关闭打开的文件(因为有一个文件描述符足以让UNIX写入文件,你没有需要保持资源打开),然后将打开的文件分配给sys.stdout
。
记住sys
是Python模块,它代表各种特定于系统的资源,例如文件系统。因此,在UNIX sys.stdout
中将代表/dev/stdout
,即系统STDOUT
流。
所以,总而言之,这段代码愚弄Python认为/dev/null/
是STDOUT
所以现在每次你的程序用STDOUT
语句写入print
时(在Python3中的功能)然后它将真正写入/dev/null
,你将永远不会在控制台上看到结果文本。
答案 2 :(得分:-1)
有关构成这些Python函数的C运行时函数,请参阅manual pages。
基本上,它们将文件描述符复制到新文件描述符(带有dup()
)或复制到调用中指定的文件描述符{.1}}。