如何进行虚拟文件处理?

98

所以我使用以下方法创建文件:

fileHandle = open('fileName', 'w')

将内容写入文件,关闭文件。接下来我会处理这个文件。在程序结束时,我需要删除一个“物理文件”。

在Python中有没有一种方法可以编写一个“虚拟”文件,它的行为方式与“物理”文件完全相同(允许以相同的方式进行操作),但在运行结束时不存在?

5个回答

90
您可以考虑使用tempfile.SpooledTemporaryFile,它能够兼顾两种优点: 一开始会创建一个基于内存的临时虚拟文件,当内存中的数据超过指定大小时,它会自动转换为基于物理磁盘的文件。
另一个不错的特性是:(在使用内存时)它会根据所用的mode自动使用io.BytesIOio.StringIO——允许您向其中读写Unicode字符串或二进制数据(字节)。
唯一需要注意的是,您需要在步骤之间避免关闭文件,因为这样做会导致文件从内存或磁盘中被删除。而应该使用文件的seek(0)方法将其倒回到开头。
当您完全使用完文件并将其关闭时,如果其中的数据量导致其被转换为物理文件,则该文件将自动从磁盘中删除。

请参考以下相关示例:https://dev59.com/lmoy5IYBdhLWcg3wZtNC - Anton Tarasenko
5
从另一个问题跳转过来,值得注意的是这个暂存在内存中的临时文件没有文件名(需要通过处理器操作)。然而对于提问者的使用场景而言,这个解决方案非常好(赞 +1)。不幸的是,在这个模块中缺少 tempfile.NamedSpooledTemporaryFile()NamedTemporaryFile()SpooledTemporaryFile() 的组合)这一功能。 - WoJ
@WoJ:谢谢你的点赞。我认为没有 tempfile.NamedSpooledTemporaryFile() 的原因是,一个起始于基于内存的虚拟文件的东西不可能保证在文件系统中有一个可见的名称——尽管如果它的大小超过了指定的 max_size 阈值,它 可能 会有一个名称。tempfile 模块的源代码位于 python/Lib/tempfile.py,如果您想要自己实现所需的行为(无论当前数据是否在内存中),这可能会有所帮助。 - martineau

61

io模块中有StringIOBytesIO

StringIO的行为类似于以文本模式打开的文件——读写Unicode字符串(相当于使用io.open(filename, mode, encoding='...')打开文件),而BytesIO的行为类似于以二进制模式打开的文件(mode='[rw]b'),可以读写字节。

Python 2:

In [4]: f = io.BytesIO('test')
In [5]: type(f.read())
Out[5]: str
In [6]: f = io.StringIO(u'test')
In [7]: type(f.read())
Out[7]: unicode

Python 3:

In [2]: f = io.BytesIO(b'test')
In [3]: type(f.read())
Out[3]: builtins.bytes
In [4]: f = io.StringIO('test')
In [5]: type(f.read())
Out[5]: builtins.str


13

您可以使用StringIO作为虚拟文件,来自官方文档

from io import StringIO

output = StringIO()
output.write('First line.\n')
print >>output, 'Second line.'

# Retrieve file contents -- this will be
# 'First line.\nSecond line.\n'
contents = output.getvalue()

# Close object and discard memory buffer --
# .getvalue() will now raise an exception.
output.close()

11
请记住,如果您想将其作为类似文件的对象传递给另一个函数,您应该使用以下代码倒回虚拟文件: output.seek(0) - RufusVS
1
哥们,你是从官方文档复制粘贴的吗? :) 我觉得在这种情况下使用链接是公平的。 - maxadamo
@maxadamo 完成了。谢谢。 - Srinivas Reddy Thatiparthy
2
从Python >= 3中导入StringIO模块。 - Christof

0

StringIO 模块,阅读其文档,应该很容易使用。

请记住,这将在内存中保留“文件”的内容。如果您有太多数据,最好创建一个真实的文件,例如在 /tmp 中,并在使用后删除它。


0
如果您的意思是将文本写入内存而不是文件,您可以将文本写入缓冲区并使用以下函数:
def write(text):
  global buffer
  buffer += text + '\n'  # Add a linefeed as you would if you were writing to a file

buffer = ""  # Initialize the buffer
write("My name is Steve Grafton")

最后,您将拥有一个缓冲区,它与您将内容写入文件,然后打开文件并读取所有内容到缓冲区相同!此外,在过程中(在完成写作之前),您可以使用缓冲区进行搜索,就像创建了一个用于读写的文件一样,只是在这种情况下,您的指针将会

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接