0

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

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在测试期间伪造文件系统,它会崩溃并出现一个令人困惑的错误(IsADirectoryError: [Errno 21] Is a directory在 ubuntu 和PermissionError: [Errno 13] Permission deniedWindows 上)——甚至不需要对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模块,所以我可能只是使用错误(我的实际用例是在开发过程中创建一个文件,并避免使用__file__找到正确的位置)。

4

1 回答 1

1

请参阅pyfakefs 文档,其中指出:

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

  • os 和 os.path 模块中的大多数文件系统相关功能
  • 路径库模块
  • 内置 open 函数和 io.open
  • shutil.disk_usage

简单地包括fs夹具就可以修补这些模块。如果您确实需要使用pyfakefs,请提供您的代码期望的所有内容(甚至是间接的),或者以 paused 开始您的测试,fs并使其仅用于测试无法以其他方式测试的特定事物。在这种情况下,它io.open会中断。


fs.add_real_directory通过在执行依赖于文件存在的函数之前调用来提供预期的文件,如下所示:

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

, whereimportlib.__file__需要替换为importlib.resources.path在测试代码中访问的任何内容的完整路径。这种方法对于在测试函数中创建文件也是安全的,因为假 fs 知道所有更改并且从不将它们应用于实际文件:

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

于 2019-12-03T15:50:58.350 回答