这是here的后续问题。
我希望能够暂时将stdout重定向到临时文件,而python仍然能够打印到stdout。这将涉及以下步骤:
new
)tmp
)tmp
new
作为stdouttmp
重定向到“真正的”标准输出tmp
我试图通过以下方式实现上述目标:
import os
import subprocess
import sys
#A function that calls an external process to print to stdout as well as
#a python print to pythons stdout.
def Func(s, p = False):
subprocess.call('echo "{0}"'.format(s), shell = True)
if p:
print "print"
sil = list() # <-- Some list to store the content of the temp files
print "0.1" # Some testing of the
Func("0.2") # functionality
new = os.dup(1) # Create a copy of stdout (new)
tmp = os.tmpfile() # Create a temp file (tmp)
os.dup2(tmp.fileno(), 1) # Redirect stdout into tmp
sys.stdout = os.fdopen(new, 'w', 0) # Tell python to use new as stdout
Func("0.3", True) # <--- This should print "0.3" to the temp file and "print" to stdout
os.dup2(new, 1) # Redirect tmp into "real" stdout
sys.stdout = os.fdopen(1, 'w', 0) # Tell python to use "real" stdout again
# Read and close tmp
tmp.flush()
tmp.seek(0, os.SEEK_SET)
sil.append(tmp.read())
tmp.close()
我想在此稍作总结。
到这里为止,控制台的输出应该是:
0.1
0.2
print
而sil
应该是这样的:['0.3\n']
。所以到现在为止,一切都在运转。但是,如果我再次像这样重做上面的脚本:
print "1.1" # Some testing of the
Func("1.2") # functionality
new = os.dup(1) # Create a copy of stdout (new)
tmp = os.tmpfile() # Create a temp file (tmp)
os.dup2(tmp.fileno(), 1) # Redirect stdout into tmp
sys.stdout = os.fdopen(new, 'w', 0) # Tell python to use new as stdout
# This should print "0.3" to the temp file and "print" to stdout and is the crucial point!
Func("1.3", True)
os.dup2(new, 1) # Redirect tmp into "real" stdout
sys.stdout = os.fdopen(1, 'w', 0) # Tell python to use "real" stdout again
# Read and close tmp
tmp.flush()
tmp.seek(0, os.SEEK_SET)
sil.append(tmp.read())
出现错误,输出如下:
1.1
1.2
/bin/sh: line 0: echo: write error: Bad file descriptor
print
而sil
读取:['0.3\n', '']
。
换句话说:第二个Func("1.3", True)
无法写入临时文件。
dup
和dup2
的用法还是有点困惑。虽然我想我了解将stdout重定向到临时文件的工作原理,但我现在完全知道为什么os.dup2(new, 1)
在做它正在做的事情。也许答案可以详细说明我的脚本中所有的dup
和dup2
都在做什么^ ^
得到“坏文件描述符”的原因是垃圾收集器为您关闭stdout FD。考虑这两条线:
现在,当这两个文件对象中的第二个被执行时,第一个文件对象的引用计数将降为零,垃圾收集器将其销毁。文件对象在被销毁时关闭其关联的fd,而fd恰好是1=stdout。因此,在销毁使用
os.fdopen
创建的对象时需要非常小心。这里有一个小例子来说明这个问题。
os.fstat
只是用作一个示例函数,当您向它传递一个关闭的fd时,它会触发“坏文件描述符”错误。实际上,我正好有一个上下文管理器,我认为它确实(或者至少,在我的情况下,我需要一个命名的tempfile)满足您的需要。您可以看到它重用了原来的sys.stdout对象,以避免close出现问题。
相关问题 更多 >
编程相关推荐