`shutil.rmtree` 不适用于 `tempfile.TemporaryDirectory()`
`shutil.rmtree` does not work on `tempfile.TemporaryDirectory()`
考虑这个测试
import shutil, tempfile
from os import path
import unittest
from pathlib import Path
class TestExample(unittest.TestCase):
def setUp(self):
# Create a temporary directory
self.test_dir = tempfile.TemporaryDirectory()
self.test_dir2 = tempfile.mkdtemp()
def tearDown(self):
# Remove the directory after the test
shutil.rmtree(self.test_dir2)
shutil.rmtree(self.test_dir.name) #throws error
def test_something(self):
self.assertTrue(Path(self.test_dir.name).is_dir())
self.assertTrue(Path(self.test_dir2).is_dir())
if __name__ == '__main__':
unittest.main()
在 tearDown
但是出现错误
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpxz7ts7a7'
指的是self.test_dir.name
.
根据the source code for tempfile
,两个元素相同。
def __init__(self, suffix=None, prefix=None, dir=None):
self.name = mkdtemp(suffix, prefix, dir)
self._finalizer = _weakref.finalize(
self, self._cleanup, self.name,
warn_message="Implicitly cleaning up {!r}".format(self))
而且我没有在上下文中使用它,因此据我所知不应调用 __exit__()
。
发生了什么事?
不要用 shutil
清理这些。 tempfile.TemporaryDirectory
class 提供了一个 cleanup()
方法,如果您想选择加入显式清理,只需调用它即可。
您的代码崩溃的原因是 TemporaryDirectory
class 设计为在超出范围后自行清理(引用计数为零)。但是,由于您已经手动从文件系统中删除了该目录,因此当实例随后尝试删除自身时,拆卸会失败。 "No such file or directory" 错误来自 TemporaryDirectory
自己的拆解,而不是来自您的 shutil.rmtree
行!
与上下文无关:
import tempfile,os
t = tempfile.TemporaryDirectory()
s = t.name
print(os.path.isdir(s))
# os.rmdir(s) called here triggers error on the next line
t = None
print(os.path.isdir(s))
它打印
True
False
因此,一旦 t
的引用设置为 None
,对象就会被垃圾回收并删除目录,如 documentation 所述:
On completion of the context or destruction of the temporary directory object the newly created temporary directory and all its contents are removed from the filesystem.
取消注释下面代码段中的 os.rmdir(s)
会在对象完成时抛出异常:
Exception ignored in: <finalize object at 0x20b20f0; dead>
Traceback (most recent call last):
File "L:\Python34\lib\weakref.py", line 519, in __call__
return info.func(*info.args, **(info.kwargs or {}))
File "L:\Python34\lib\tempfile.py", line 698, in _cleanup
_shutil.rmtree(name)
File "L:\Python34\lib\shutil.py", line 482, in rmtree
return _rmtree_unsafe(path, onerror)
File "L:\Python34\lib\shutil.py", line 364, in _rmtree_unsafe
onerror(os.listdir, path, sys.exc_info())
File "L:\Python34\lib\shutil.py", line 362, in _rmtree_unsafe
names = os.listdir(path)
所以你的调用可能成功了,但是你在对象结束时得到了异常(紧接着)
调用 cleanup()
对象方法而不是 rmtree
解决了问题,因为对象内部状态更新为 而不是 尝试删除目录时完成(如果你问我,对象 应该 在尝试清理目录之前测试目录是否存在,但即使那样也不总是有效,因为它不是原子操作)
所以替换
shutil.rmtree(self.test_dir.name)
来自
self.test_dir.cleanup()
或者什么都不做,让对象在删除时清理目录。
考虑这个测试
import shutil, tempfile
from os import path
import unittest
from pathlib import Path
class TestExample(unittest.TestCase):
def setUp(self):
# Create a temporary directory
self.test_dir = tempfile.TemporaryDirectory()
self.test_dir2 = tempfile.mkdtemp()
def tearDown(self):
# Remove the directory after the test
shutil.rmtree(self.test_dir2)
shutil.rmtree(self.test_dir.name) #throws error
def test_something(self):
self.assertTrue(Path(self.test_dir.name).is_dir())
self.assertTrue(Path(self.test_dir2).is_dir())
if __name__ == '__main__':
unittest.main()
在 tearDown
但是出现错误
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpxz7ts7a7'
指的是self.test_dir.name
.
根据the source code for tempfile
,两个元素相同。
def __init__(self, suffix=None, prefix=None, dir=None):
self.name = mkdtemp(suffix, prefix, dir)
self._finalizer = _weakref.finalize(
self, self._cleanup, self.name,
warn_message="Implicitly cleaning up {!r}".format(self))
而且我没有在上下文中使用它,因此据我所知不应调用 __exit__()
。
发生了什么事?
不要用 shutil
清理这些。 tempfile.TemporaryDirectory
class 提供了一个 cleanup()
方法,如果您想选择加入显式清理,只需调用它即可。
您的代码崩溃的原因是 TemporaryDirectory
class 设计为在超出范围后自行清理(引用计数为零)。但是,由于您已经手动从文件系统中删除了该目录,因此当实例随后尝试删除自身时,拆卸会失败。 "No such file or directory" 错误来自 TemporaryDirectory
自己的拆解,而不是来自您的 shutil.rmtree
行!
与上下文无关:
import tempfile,os
t = tempfile.TemporaryDirectory()
s = t.name
print(os.path.isdir(s))
# os.rmdir(s) called here triggers error on the next line
t = None
print(os.path.isdir(s))
它打印
True
False
因此,一旦 t
的引用设置为 None
,对象就会被垃圾回收并删除目录,如 documentation 所述:
On completion of the context or destruction of the temporary directory object the newly created temporary directory and all its contents are removed from the filesystem.
取消注释下面代码段中的 os.rmdir(s)
会在对象完成时抛出异常:
Exception ignored in: <finalize object at 0x20b20f0; dead>
Traceback (most recent call last):
File "L:\Python34\lib\weakref.py", line 519, in __call__
return info.func(*info.args, **(info.kwargs or {}))
File "L:\Python34\lib\tempfile.py", line 698, in _cleanup
_shutil.rmtree(name)
File "L:\Python34\lib\shutil.py", line 482, in rmtree
return _rmtree_unsafe(path, onerror)
File "L:\Python34\lib\shutil.py", line 364, in _rmtree_unsafe
onerror(os.listdir, path, sys.exc_info())
File "L:\Python34\lib\shutil.py", line 362, in _rmtree_unsafe
names = os.listdir(path)
所以你的调用可能成功了,但是你在对象结束时得到了异常(紧接着)
调用 cleanup()
对象方法而不是 rmtree
解决了问题,因为对象内部状态更新为 而不是 尝试删除目录时完成(如果你问我,对象 应该 在尝试清理目录之前测试目录是否存在,但即使那样也不总是有效,因为它不是原子操作)
所以替换
shutil.rmtree(self.test_dir.name)
来自
self.test_dir.cleanup()
或者什么都不做,让对象在删除时清理目录。