快速变化目录的递归通配
Recursive globbing of fast-changing directories
我偶然发现了一个不直观的问题:如果你递归地 glob(使用 pathlib)快速变化的目录,在其他目录被创建和删除的地方,你有机会得到 FileNotFoundException
。如果找不到目录,那为什么要用这个来打扰我呢?为什么不跳过虚假目录并继续呢?我如何以紧凑的方式解决这个问题?
重现方法如下:
用这个 sh 命令启动一个终端
while true; do mkdir deleteme && rmdir deleteme; done
另一个使用这个 python 脚本:
from pathlib import Path
p = Path()
while True:
list(p.rglob('*'))
或者,作为一个班轮:
while true; do mkdir 1 && rmdir 1; done & python3 -c "from pathlib import Path; from itertools import count; p = Path(); [list(p.rglob('*')) for i in count(start=1)]"; fg
产生异常的原语是os.scandir
。
发生的事情是 pathlib.Path.rglob()
方法创建一个选择器对象(pathlib._WildcardSelector
通过 pathlib._make_selector
,给定你的模式),然后在执行rglob()
生成器。
pathlib
模块似乎没有提供任何挂钩来轻松自定义或覆盖此行为。
最好的解决方案可能是子class Path
或 PosixPath
class,覆盖 rglob()
方法,在对这种错误模式有弹性的方式。
似乎可以作为概念证明的猴子补丁方法:
import contextlib
import pathlib
def my_scandir(path=None):
while True:
try:
result = list(os.scandir(path))
except FileNotFoundError:
continue
@contextlib.contextmanager
def wrapped_result():
try:
yield result
finally:
pass
return wrapped_result()
pathlib._NormalAccessor.scandir = staticmethod(my_scandir)
应用此补丁后,示例中带有 rglob('*')
的 while 循环不再因 FileNotFoundError
.
而失败
这适用于 Python v3.8.5。因为它使用了 pathlib 模块的实现细节,所以它可能不适用于其他 python 版本。
我偶然发现了一个不直观的问题:如果你递归地 glob(使用 pathlib)快速变化的目录,在其他目录被创建和删除的地方,你有机会得到 FileNotFoundException
。如果找不到目录,那为什么要用这个来打扰我呢?为什么不跳过虚假目录并继续呢?我如何以紧凑的方式解决这个问题?
重现方法如下:
用这个 sh 命令启动一个终端
while true; do mkdir deleteme && rmdir deleteme; done
另一个使用这个 python 脚本:
from pathlib import Path
p = Path()
while True:
list(p.rglob('*'))
或者,作为一个班轮:
while true; do mkdir 1 && rmdir 1; done & python3 -c "from pathlib import Path; from itertools import count; p = Path(); [list(p.rglob('*')) for i in count(start=1)]"; fg
产生异常的原语是os.scandir
。
发生的事情是 pathlib.Path.rglob()
方法创建一个选择器对象(pathlib._WildcardSelector
通过 pathlib._make_selector
,给定你的模式),然后在执行rglob()
生成器。
pathlib
模块似乎没有提供任何挂钩来轻松自定义或覆盖此行为。
最好的解决方案可能是子class Path
或 PosixPath
class,覆盖 rglob()
方法,在对这种错误模式有弹性的方式。
似乎可以作为概念证明的猴子补丁方法:
import contextlib
import pathlib
def my_scandir(path=None):
while True:
try:
result = list(os.scandir(path))
except FileNotFoundError:
continue
@contextlib.contextmanager
def wrapped_result():
try:
yield result
finally:
pass
return wrapped_result()
pathlib._NormalAccessor.scandir = staticmethod(my_scandir)
应用此补丁后,示例中带有 rglob('*')
的 while 循环不再因 FileNotFoundError
.
这适用于 Python v3.8.5。因为它使用了 pathlib 模块的实现细节,所以它可能不适用于其他 python 版本。