我正在努力为接受os.DirEntry
对象的函数添加类型提示(这些由os.scandir()
生成)。这是一个接受DirEntry
个对象的简单访问者类:
class FileSystemVisitor:
def visit_dir(self, entry) -> None:
...
def visit_file(self, entry) -> None:
...
FileSystemVisitor
的实例正被送到visit()
函数,该函数遍历给定目录的子树:
def traverse(path: Union[str, pathlib.Path], visitor: FileSystemVisitor) -> None:
for entry in os.scandir(str(path)):
if entry.is_dir(follow_symlinks=False):
visitor.visit_dir(entry)
traverse(entry.path, visitor)
else:
visitor.visit_file(entry)
如何在entry
函数中为FileSystemVisitor.visit_{dir(),file()}
参数添加类型提示?我无法导入DirEntry
。
$ python3.5 -c "from os import DirEntry"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: cannot import name 'DirEntry'
我能想到的一件事是编写一个模仿DirEntry
的虚拟类并将其用于类型提示:
class DirEntryType:
name = None # type: str
path = None # type: str
def inode(self) -> int:
...
def is_dir(self) -> bool:
...
def is_file(self) -> bool:
...
def is_symlink(self) -> bool:
...
def stat(self) -> os.stat_result:
...
然而,是否只为聪明的类型提示添加了一个完整的类?
如果这很重要,我会遇到python3.5
,因此无法使用python3.6
的功能。
正如avigil在评论中指出的那样,DirEntry
可以导入python3.6
:
$ python3.6 -c "from os import DirEntry; print(DirEntry)"
<class 'posix.DirEntry'>
向后兼容的解决方案因此可以是例如:
# typing_utils.py
class DirEntryStub:
name = None # type: str
path = None # type: str
def inode(self) -> int:
raise NotImplementedError('This class is used for type hints only')
def is_dir(self, follow_symlinks: bool = False) -> bool:
raise NotImplementedError('This class is used for type hints only')
def is_file(self, follow_symlinks: bool = False) -> bool:
raise NotImplementedError('This class is used for type hints only')
def is_symlink(self) -> bool:
raise NotImplementedError('This class is used for type hints only')
def stat(self) -> os.stat_result:
raise NotImplementedError('This class is used for type hints only')
现在我可以输入FileSystemVisitor
:
try:
from os import DirEntry
except ImportError:
from typing_utils import DirEntryStub as DirEntry
class FileSystemVisitor:
def visit_dir(self, entry: DirEntry) -> None:
...
def visit_file(self, entry: DirEntry) -> None:
...
答案 0 :(得分:1)
DirEntry
在posix模块中的C中实现,但不幸的是,在3.6版本发布之前,它未在python中保留。有关相关的python bug跟踪器问题,请参阅bpo-27038。
对于早期版本,您可以按照建议进行操作并将其删除,除非您足够谨慎地完成编译自己patched version的工作。由于scandir
实现最初来自scandir包,可以修补并作为依赖项引入,以支持标准,因此实际上不会太图书馆实施。