Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么在I';你把它拆开了?_Python_Python 3.x_Spyder - Fatal编程技术网

Python 为什么在I';你把它拆开了?

Python 为什么在I';你把它拆开了?,python,python-3.x,spyder,Python,Python 3.x,Spyder,我编写了一个tee() 它在我的程序运行的前几次运行时起作用,但在第三次运行时: 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 似乎即使在我执行了s

我编写了一个
tee()

它在我的程序运行的前几次运行时起作用,但在第三次运行时:

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

这里的危险在于设置
sys.stdout=sys.old\u 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\u dest
会被分配一个值,因此将
sys.stdout
更改回其旧值并不能阻止它继续尝试使用您现在已失效的对象。

@CharlesDuffy但是
self.name=None
仅在
sys.stdout=self.old\u stdout
之后发生,它恢复标准输出以运行旧代码。在那之后,我的write方法就不应该被调用了。(除非我非常困惑)啊,明白了。问题是,
sys.stdout=self.old\u stdout
仅适用于每次要执行写入操作时都要通过
sys
模块的代码。假设您有一个以类似于
类MyThread(threading.thread):def\u init(self,log\u dest=sys.stdout,…)的初始值设定项启动的线程
——对于任何已启动的线程副本,
log\u dest
不会神奇地变回。这只是一个示例,旨在演示在更改sys模块的引用后,假设没有剩余句柄是不安全的。@CharlesDuffy Ya,可能就是这样。有道理。我会在心里测试一个mod,如果它有效的话,你应该给出一个答案。是的,就是这样。如果
self.name为None,将write方法更改为只执行
print(text)
,似乎可以解决这个问题。要让它可靠地工作,这是一件棘手的事情。