为什么在取消链接后调用我的 revectored sys.stdout.write() 方法?
Why does my revectored sys.stdout.write() method get called after I've unlinked it?
我写了一个 tee()
class,它根据 Triptych 在 的回答将 stdout 重定向到终端和文件
它在我的程序运行的前几次有效,但第三次我得到:
File "C:\Users\Dave\data\Code\Python\lib\nerdlib.py", line 351, in write
with open(self.name, "a", encoding="utf-8") as f:
TypeError: expected str, bytes or os.PathLike object, not NoneType
似乎即使我做了 sys.stdout = self.old_stdout
(将执行向量恢复到它开始的地方),我的 write 方法仍然以某种方式被调用(在这种情况下会出现错误)。
但是为什么我的方法仍然被调用?
此错误发生在 Spyder 开发环境中 - 不确定是否相关。
代码如下 - 很简单。
# based on Triptych's answer at
class tee():
''' Tees stdout to both a log file and the terminal.
if append is True (default), appends to existing file
if stderr is True (default), tees stederr to same file
Usage:
t = tee("filename.txt")
...
print(1, 2, 3)
...
t.__del__() # returns sys.stdout to original state
'''
def __init__(self, filepath, append=True, stderr=True):
self.old_stdout = sys.stdout
self.old_stderr = sys.stderr
self.name = filepath
if (not append) or (not os.path.exists(self.name)):
makeEmptyFile(self.name)
sys.stdout = self
if stderr:
sys.stderr = self
def write(self, text):
self.old_stdout.write(text)
# open file, write, then close it again (slow, but safe - permits other processes to write to same file)
with open(self.name, "a", encoding="utf-8") as f:
f.write(text)
def flush(self):
pass
def stop(self):
sys.stdout = self.old_stdout
sys.stdout = self.old_stderr
self.name = None
def __del__(self):
self.stop()
这里的危险是设置 sys.stdout = sys.old_stdout
会阻止代码在本地替换上获得 new 句柄,但不会阻止任何 旧的 句柄无法工作。
举个例子:
class MyThread(threading.Thread):
def __init__(self, log_dest=sys.stdout):
self.log_dest = log_dest
def run(self):
# ...do something-or-other, and occasionally...
self.log_dest.write('Hey, something happened')
因为 log_dest
在 MyThread 初始化时 被分配了一个值 ,将 sys.stdout
改回其旧值并不会阻止它仍然尝试使用您现在无效的对象。
我写了一个 它在我的程序运行的前几次有效,但第三次我得到: 似乎即使我做了 但是为什么我的方法仍然被调用? 此错误发生在 Spyder 开发环境中 - 不确定是否相关。 代码如下 - 很简单。tee()
class,它根据 Triptych 在 的回答将 stdout 重定向到终端和文件
File "C:\Users\Dave\data\Code\Python\lib\nerdlib.py", line 351, in write
with open(self.name, "a", encoding="utf-8") as f:
TypeError: expected str, bytes or os.PathLike object, not NoneType
sys.stdout = self.old_stdout
(将执行向量恢复到它开始的地方),我的 write 方法仍然以某种方式被调用(在这种情况下会出现错误)。# based on Triptych's answer at
class tee():
''' Tees stdout to both a log file and the terminal.
if append is True (default), appends to existing file
if stderr is True (default), tees stederr to same file
Usage:
t = tee("filename.txt")
...
print(1, 2, 3)
...
t.__del__() # returns sys.stdout to original state
'''
def __init__(self, filepath, append=True, stderr=True):
self.old_stdout = sys.stdout
self.old_stderr = sys.stderr
self.name = filepath
if (not append) or (not os.path.exists(self.name)):
makeEmptyFile(self.name)
sys.stdout = self
if stderr:
sys.stderr = self
def write(self, text):
self.old_stdout.write(text)
# open file, write, then close it again (slow, but safe - permits other processes to write to same file)
with open(self.name, "a", encoding="utf-8") as f:
f.write(text)
def flush(self):
pass
def stop(self):
sys.stdout = self.old_stdout
sys.stdout = self.old_stderr
self.name = None
def __del__(self):
self.stop()
这里的危险是设置 sys.stdout = sys.old_stdout
会阻止代码在本地替换上获得 new 句柄,但不会阻止任何 旧的 句柄无法工作。
举个例子:
class MyThread(threading.Thread):
def __init__(self, log_dest=sys.stdout):
self.log_dest = log_dest
def run(self):
# ...do something-or-other, and occasionally...
self.log_dest.write('Hey, something happened')
因为 log_dest
在 MyThread 初始化时 被分配了一个值 ,将 sys.stdout
改回其旧值并不会阻止它仍然尝试使用您现在无效的对象。