开发者社区> 问答> 正文

取消链接后,为什么重新调用了sys.stdout.write()方法?

我写了一个tee()类,该类基于Triptych在https://stackoverflow.com/questions/616645/how-do-i-duplicate-sys-stdout-上的答案将stdout重定向到终端和文件 到 python中的日志文件。

它在我的程序运行的前几次有效,但在第3次运行时有效:

  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 https://stackoverflow.com/questions/616645/how-do-i-duplicate-sys-stdout-to-a-log-file-in-python
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()

问题来源:stackoverflow

展开
收起
is大龙 2020-03-24 19:06:08 586 0
1 条回答
写回答
取消 提交回答
  • 这里的危险是,设置sys.stdout = sys.old_stdout会阻止代码在本地替换上获得新的句柄,但不会阻止任何旧的 句柄正常工作。

    作为一个人为的例子:

    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')
    

    由于初始化MyThread时会为log_dest分配一个值,因此将sys.stdout更改回其旧值不会阻止它继续尝试使用现在无效的对象。

    回答来源:stackoverflow

    2020-03-24 19:06:17
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载