从Python重定向c呼叫
-
26-10-2019 - |
题
从python模块我称 你好世界 可执行的简单打印 Hello World
到stdout。我有兴趣将该输出重定向到Python StringIO
并遇到 这个 回答几乎使我一路走向解决方案。
该答案的关键部分是该代码段:
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
? - 8行在做什么? ((
sys.stdout = os.fdopen(newstdout, 'w')
)
- 什么是
- 我该如何将Stdout存储在
StringIO
目的? - 打电话给我的电话后,我该如何恢复stdout 你好世界 程序?
我很确定,一旦有了问题1的答案,问题2和3的答案将很容易。我决定将它们发布到任何时候,以将问题1的答案推向我想去的方向。
解决方案
我在下面写了一些其他评论,这些评论应该更清楚地表明它正在发生什么 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')
要注意的一件重要的事情是,一个过程获得了三个不同的 文件描述符 启动时从操作系统中:
- stdin:0
- Stdout:1
- Stderr:2
如评论中所述,上面的代码利用了stdout的文件描述符和文件描述符重复功能,以使技巧C代码使用不同的stdout,同时仍在对Python代码中的原始stdout进行引用,以便能够打印。
其他提示
/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
而且,您将永远不会在控制台上看到结果文字。
看 手动页面 对于C运行时功能,这些功能是这些Python函数的基础。
基本上,他们将文件描述符复制到一个新文件描述符中(带有 dup()
)或在呼叫中指定的文件描述符中, dup2()
.