从python为C调用重定向stdout

2024-10-03 21:32:45 发布

您现在位置:Python中文网/ 问答频道 /正文

这是一个来自here的后续问题,特别是关于它的answer。在


在python模块中,我调用了一个helloworld可执行文件,它只需将Hello World打印到stdout。我有兴趣将输出重定向到python StringIO并遇到{a3}答案,这几乎让我找到了解决方案。在

这个答案的关键部分是以下代码段:

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,因为它是在重定向之前。在

问题

  1. 上面的函数到底是怎么回事?
    • dup和{}在做什么?在
    • 什么是/dev/null?在
    • 8号线在干什么?(sys.stdout = os.fdopen(newstdout, 'w')
  2. 如何将stdout存储在StringIO对象中?在
  3. 在调用我的Hello World程序后,如何恢复stdout?在

我很肯定,一旦我有了问题1的答案,问题2和3的答案将很容易。我决定无论如何都把它们贴出来,也许可以把问题1的答案推到我想去的地方。在


Tags: 答案devhelloworldhereosstdoutsys
3条回答

我在下面写了一些附加的注释,这些注释应该可以更清楚地说明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

  • 标准输入:0
  • 标准输出:1
  • 标准:2

正如注释中所解释的,上面的代码利用stdout的文件描述符和文件描述符复制函数来欺骗C代码使用不同的stdout,同时仍然在python代码中保留对原始stdout的引用,以便能够打印。在

请参见manual pages,了解作为这些Python函数基础的C运行时函数。在

基本上,它们将一个文件描述符复制到一个新的文件描述符(使用dup())或使用dup2()复制到调用中指定的文件描述符中。在

/dev/null是一个特殊的设备文件(UNIX中的所有文件都是一个文件!)它像黑洞一样吞没了所有写在上面的东西。dup复制文件描述符。如果您习惯于Windows,UNIX中的文件描述符是一个特殊的整数,它表示一个打开的文件,它类似于Windows文件句柄。在

程序正在打开/dev/null进行写入(仅限),获取其文件描述符的副本,关闭打开的文件(因为对于UNIX来说,有一个文件描述符就足够了,您不需要保持资源打开),然后将打开的文件分配给sys.stdout。在

请记住,sys是Python模块,它代表各种特定于系统的资源,例如文件系统。因此,在UNIX中sys.stdout将表示/dev/stdout,即系统STDOUT流。在

总之,这段代码欺骗了Python,让它认为/dev/null/是{},所以现在每当你的程序用print语句(Python3中的函数)写入/dev/null/时,它实际上是在写/dev/null,你永远不会在控制台上看到结果文本。在

相关问题 更多 >