如何将pyfakefs与importlib.resources.path结合使用

时间:2019-12-03 15:13:42

标签: python pytest python-3.7 python-importlib pyfakefs

给出一些已安装的软件包,以下代码可用于在文件系统上打印其位置:

import importlib.resources

def print_package_path():
    with importlib.resources.path("importlib", "") as path:
        print(path)

if __name__ == "__main__":
    print_package_path()  # /home/me/python_3.8/lib/python3.8/importlib on my machine

如果我想测试包含这样的语句的函数,其中该语句包含pytest作为测试套件,而pyfakefs在测试期间伪造文件系统,则它将崩溃,并产生一个令人困惑的错误({{1 }}(在Ubuntu上,IsADirectoryError: [Errno 21] Is a directory在Windows上)-甚至不需要使用PermissionError: [Errno 13] Permission denied固定装置执行任何操作,只需在运行代码时就可以使用它。

fs执行此功能

pytest

将导致

def test_package_path(fs):
    print_package_path()

这对我来说意义非零。首先应该不会把目录用作资源吗?

我必须承认我不太了解______________________________ test_package_path _______________________________ fs = <pyfakefs.fake_filesystem.FakeFilesystem object at 0x7f84f2996910> def test_package_path(fs): > print_package_path() /home/me/foo.py:11: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /home/me/foo.py:4: in print_package_path with importlib.resources.path("importlib", "") as path: /home/me/pythons/python_3.8/lib/python3.8/contextlib.py:113: in __enter__ return next(self.gen) /home/me/venv/lib/python3.8/importlib/resources.py:201: in path with open_binary(package, resource) as fp: /home/me/venv/lib/python3.8/importlib/resources.py:91: in open_binary return reader.open_resource(resource) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <_frozen_importlib_external.SourceFileLoader object at 0x7f84f7527370> resource = '' > ??? E IsADirectoryError: [Errno 21] Is a directory: '/home/me/venv/lib/python3.8/importlib' <frozen importlib._bootstrap_external>:988: IsADirectoryError 模块,所以我可能只是在错误地使用它(我的实际用例是在开发过程中创建文件,并避免使用importlib.resources找到正确的位置。

1 个答案:

答案 0 :(得分:1)

请参见pyfakefs documentation,其中指出:

  

由于某些原因,模块可能无法与pyfakefs一起使用。 pyfakefs通过修补一些与文件系统相关的模块和功能来工作,具体是:

     
      
  • os和os.path模块中与文件系统相关的大多数功能
  •   
  • pathlib模块
  •   
  • 内置打开功能和io.open
  •   
  • shutil.disk_usage
  •   

仅包含fs固定装置就可以修补这些模块。如果您确实需要使用pyfakefs,则可以提供代码期望的所有内容(甚至是间接提供的),也可以使用暂停的fs开始测试,并使其仅用于测试无法测试的特定内容。在这种情况下,io.open中断了。


在执行依赖于文件存在的功能之前,调用fs.add_real_directory可提供期望的文件,如下所示:

def test_package_path(fs):
    fs.add_real_directory(os.path.dirname(importlib.__file__))
    print_package_path()

,其中importlib.__file__需要替换为测试代码中importlib.resources.path访问的内容的完整路径。此方法对于在经过测试的函数中创建文件也很安全,因为伪造的fs知道所有更改,并且永远不会将其应用于实际文件:

  

默认情况下,对文件的访问是只读的,但是即使您使用read_only = False进行添加,文件也只能写在伪造的系统中(例如,在内存中)。真实文件永远不会改变。