Python:如何在测试套件中创建临时文件?
(我正在使用 Python 2.6 和 nose
。)
我正在为我的 Python 应用程序编写测试。我想要一个测试来打开一个新文件,关闭它,然后删除它。当然,我更喜欢这发生在临时目录中,因为我不想破坏用户的文件系统。而且,它需要是跨操作系统的。
我该怎么做?
(I'm using Python 2.6 and nose
.)
I'm writing tests for my Python app. I want one test to open a new file, close it, and then delete it. Naturally, I prefer that this will happen inside a temporary directory, because I don't want to trash the user's filesystem. And, it needs to be cross-OS.
How do I do it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
FWIW 使用 py.test 您可以编写:
使用“tmpdir”函数参数的每个测试函数将获得一个干净的空目录,创建为“/tmp/pytest-NUM”的子目录(linux,win32 有不同的路径),其中 NUM每次测试运行都会增加。保留最后三个目录以便于检查,旧的目录将被自动删除。您还可以使用 py.test --basetemp=mytmpdir 设置基本临时目录。
tmpdir 对象是一个 py.path.local 对象,也可以像这样使用:
但也可以将其转换为“字符串”路径:
FWIW using py.test you can write:
Each test function using the "tmpdir" function argument will get a clean empty directory, created as a sub directory of "/tmp/pytest-NUM" (linux, win32 has different path) where NUM is increased for each test run. The last three directories are kept to ease inspection and older ones are automatically deleted. You can also set the base temp directory with
py.test --basetemp=mytmpdir
.The tmpdir object is a py.path.local object which can also use like this:
But it's also fine to just convert it to a "string" path:
请参阅标准库中的 tempfile 模块
以下是 使用
TemporaryFile
和TemporaryDirectory
的示例 > 作为上下文管理器:See the tempfile module in the standard library
Here are the examples of using
TemporaryFile
andTemporaryDirectory
as context managers:我建议不要直接使用 tempfile ,而是使用上下文管理器包装器 - 上下文管理器需要小心在所有情况下(成功/失败/异常)删除目录,基本上没有样板。
以下是它的使用方法:
到目前为止,当我也需要在其他地方使用它时,我一直在使用自制版本(实现相当短 - 不到 20 行),所以我环顾四周是否有准备安装的包,确实有: tempfile
注意:上面的代码片段有点过时的。
Instead of using tempfile directly I suggest using a context manager wrapper for it - the context manager takes care of removing the directory in all cases (success/failure/exception) with basically no boilerplate.
Here is how it can be used:
I have been using a home grown version (the implementation is rather short - under 20 lines) up to the point, when I needed to use it somewhere else as well, so I looked around if there is a package ready to install, and indeed there is: tempfile
Note: the code snippet above is a little out-dated.
要为测试创建包含自定义内容的临时文件,您可以使用此类:
此类将创建一个临时文件,在其中写入您的内容,然后关闭该文件。
您可以在
with
语句中使用它,以确保文件在使用后被删除,如下所示:To create a temporary file with custom content for your tests you can use this class:
This class will create a temporary file, write your content inside it and then close the file.
You use it inside a
with
statement to ensure that the file is deleted after usage like this:Python 3.2+
tempfile
库TemporaryDirectory( )
与上下文管理器携手with
是正确的出路。但是请注意,这实际上会创建临时目录(在某些操作系统目录中用于临时文件(在 Linux 上可能是/tmp
)) - 那里的文件实际上会使用存储设备/磁盘 - 它可能不会对您来说是一个问题,但是当付费服务等使用量很大时需要考虑(有关替代方案,请参阅此答案帖子的末尾)。我还建议使用
os
库os.path.join()
将内容放在那里并一般使用它以避免有关\
的跨平台错误或/
路径。注意:当不使用上下文管理器
与
时,您将获得TemporaryDirectory
类的对象并使用检索名称.name
,在上下文管理器中使用时,您将获得分配给
as
变量的名称字符串。TL;DR:代码
更改临时目录位置
在此处 您必须更深入地挖掘,因为 文档 是一种这里模糊:它根本不记录其参数,但是,它会将您发送到 mkdtemp() 应该使用相同的规则,并将您发送到 mkstemp() 您最终可以在其中确保自己使用
dir
参数来覆盖默认目录位置。您想完全伪造文件系统上的 I/O(输入/输出)操作吗?
您可以尝试按照此答案中的建议使用 pyfakefs:https://stackoverflow.com/a/46817032/1835470
哪个更好?伪造文件系统或物理临时目录?
取决于使用情况 - 通常组合可以是一个很好的折衷方案 - 使用真实的目录和文件单独测试每个文件系统操作,以便您知道它确实有效,但对于您自定义的大量使用的东西,请使用伪造/模拟文件系统操作:)另外例如,对于测试来自操作系统内部的权限 - 使用物理方式可能会更好。
您必须始终事先评估您可以获得多少性能和耐用性,以及进行额外测试是否有意义。
Python 3.2+
tempfile
libraryTemporaryDirectory()
hand in hand with context managerwith
is the way to go. However DO note, that this PHYSICALLY creates the temporary directory (in some OS dir for temp. files (on linux probably/tmp
)) - files there would actually use the storage device/disk - it may not be a problem for you, but it is something to consider when that usage would be heavy on e.g. a paid service (for alternatives see the the end of this answer post).I also suggest using
os
libraryos.path.join()
to put stuff there and to use it in general to avoid cross-platform bugs regarding\
or/
paths.Note: When used without context manager
with
you get object ofTemporaryDirectory
class and retrieve the name with.name
, when used in context manager you get the name string assigned to your
as
variable.TL;DR : The code
Change the temporary directory location
Here you must a dig a bit deeper, since documentation is kind of fuzzy here: it does not document its arguments at all, but, it sends you to mkdtemp() which should use same rules and there it sends you to mkstemp() where you can finally sort of ensure yourself, that the
dir
argument is used to override the default directory placement.Do you want to completely fake the I/O (input/output) operations on your filesystem?
You can try using pyfakefs as suggested in this answer: https://stackoverflow.com/a/46817032/1835470
Which one is better? faking filesystem or a physical temporary dir?
Depends on the usage - usually a combination can be a good compromise - test each filesystem operation on its own with real directories and files so you know it really works, but for your custom heavy-usage stuff use faking/mocking filesystem operations :) Also for testing permissions coming from within the OS for example - it would probably be better to use the physical way.
You must always evaluate beforehand how much performance and durability is available to you and if it makes sense to make an extra testing or not.
对于将来遇到此问题但由于某种原因拒绝使用 pytest 的人:
我写了 tempcase,一个小型库,它提供了一个
unittest.TestCase
子类,其中包含处理临时目录的便捷方法。在您请求目录的路径之前,不会创建目录,并且它们会根据项目、TestCase 类、时间戳和测试方法进行命名空间。之后它们会自动清理。您可以通过设置属性来禁用清理以检查输出。如果您逐步移植代码,还有一个可以应用于单个测试用例的装饰器。
For people who come across this in the future, but also refuse to use pytest for some reason:
I wrote tempcase, a small library which provides a
unittest.TestCase
subclass with convenience methods for handling temporary directories. No directories are created until you request the path to them, and they are namespaced to the project, TestCase class, timestamp, and test method. They are automatically cleaned up afterwards. You can disable cleanup to inspect the output by setting a property.There is also a decorator which can be applied to individual test cases, if you're porting code gradually.