Python 为什么调用sys.stdout.write两次?

Python 为什么调用sys.stdout.write两次?,python,python-3.x,file,stdout,write,Python,Python 3.x,File,Stdout,Write,我试图将所有打印记录到一个日志文件中(并在实际消息之前添加一个时间戳,仅在日志文件中),但我无法理解为什么调用了两次sys.stdout.write import sys from datetime import datetime class Logger(object): def __init__(self, filename="Default.log"): self.stdout = sys.stdout self.log = o

我试图将所有打印记录到一个日志文件中(并在实际消息之前添加一个时间戳,仅在日志文件中),但我无法理解为什么调用了两次
sys.stdout.write

import sys
from datetime import datetime

class Logger(object):
    def __init__(self, filename="Default.log"):
        self.stdout = sys.stdout
        self.log = open(filename, "w")

    def write(self, message):
        self.stdout.write(message)
        time_stamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
        self.log.write(f"{time_stamp} - {message}")
        self.log.flush()
    
    def flush(self):
        pass

sys.stdout = Logger("log_file.txt")
print("Hello world !")
从终端输出:

你好,世界!
在log_file.txt中输出:

2021-04-19 18:43:14.800691-你好,世界!2021-04-19 18:43:14.800735 - 
我错过了什么?在调用了
self.log.flush()
之后,会再次调用write方法,但是这里的
message='

如果我忽略了time\u stamp变量,它就像一个符咒,例如调用
self.log.write(message)

我当然可以检查消息是否为空,但我真的很想了解我的问题

我的解决方案 @伊布给了我答案!我不知道print是这样工作的:一次对数据的写调用,一次对
end
关键字的写调用,默认情况下
\n

我的解决方案是添加一个变量
self.\u hidden\u end
到被初始化为0的
Logger
类中,然后每次调用
write
时进行切换以检查它。我应该在写入日志之前添加一个时间戳

import sys
from datetime import datetime

class Logger(object):
    def __init__(self, filename="Default.log"):
        self.stdout = sys.stdout
        self.log = open(filename, "w")
        self._hidden_end = 0

    def write(self, message):
        self.stdout.write(message)
        if not self._hidden_end:
            time_stamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
            message = f"{time_stamp} - {message}"
        self._hidden_end ^= 1
        self.log.write(message)
        self.log.flush()
    
    def flush(self):
        pass

sys.stdout = Logger("log_file.txt")
print("Hello world !")

欢迎对我的上述解决方案有任何想法!:)

您感知到的结果表明调用了
文件。请写两次
:一次用于数据,一次用于“结束内容”,默认情况下这是一个换行符,可以用
end
关键字参数覆盖。有关人士证实了这一猜测

然而,这不是你应该依赖的东西。它完全是实现细节,对于另一个实现(例如PyPy)可能会有所不同,并且可能会在没有通知的情况下随时更改,更不用说覆盖内置是另一种糟糕的做法。如果没有令人信服的理由不修改代码的其他部分以使用自定义日志记录工具,那么应该避免这种做法


如果您真的需要进行monkey patching,那么重写
print()
函数更安全,因为它有一个定义的、可靠的接口。您可以导入并将新的打印函数分配给内置。打印
,保持对日志处理程序调用的控制。

恐怕这就是
print()
的工作方式-一次用于数据,一次用于换行符(即隐藏的
print(end='\n')
)非常感谢-这就解释了我的问题:)@amkleist您应该从问题中删除您的解决方案,并将其作为答案发布。而且,“关于我的解决方案的任何想法”太宽泛了。堆栈溢出用于解决有关代码的特定问题。对于一般的代码审查,可能是一个更好的地方,但记住检查他们的指导方针first@iBug请添加答案而不是评论。请参阅“我何时不应发表评论”一节?开玩笑ᴀᴍ在…上ᴇᴌᴀ 这只是一个(希望是正确的)推测,我没有检查代码或搜索任何引用。这是留下一个潜在但不完整的“答案”作为评论的一个很好的理由。