在内存中打开文件

12 投票
3 回答
35362 浏览
提问于 2025-04-18 02:28

(我正在做一个Python 3.4的项目。)

有一种方法可以在内存中打开一个(sqlite3)数据库:

    with sqlite3.connect(":memory:") as database:

有没有类似的技巧可以用在open()函数上?比如说:

   with open(":file_in_memory:") as myfile:

我的想法是加快一些测试函数在磁盘上打开、读取和写入一些短文件的速度;有没有办法确保这些操作是在内存中进行的?

3 个回答

3

io.StringIO 提供了一种内存文件的实现,你可以用它来模拟一个真实的文件。以下是文档中的示例:

import io

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

# 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()

在 Python 2 中,这个类的名称是 StringIO.StringIO

14

你觉得 StringIO 怎么样呢?

import StringIO

output = StringIO.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()

在python3中,可以使用 io.StringIO

10

在Python中,有一种类似的方式可以处理从字符串读取或写入文件的操作,这就是io.StringIO

不过,想要在正常打开文件的过程中添加基于网址的处理方式并没有简单的方法。不过,由于Python是动态语言,你可以通过“猴子补丁”的方式来修改标准的文件打开过程,以处理这种情况。

举个例子:

from io import StringIO

old_open = open
in_memory_files = {}

def open(name, mode="r", *args, **kwargs):
     if name[:1] == ":" and name[-1:] == ":":
          # in-memory file
          if "w" in mode:
               in_memory_files[name] = ""
          f = StringIO(in_memory_files[name])
          oldclose = f.close
          def newclose():
              in_memory_files[name] = f.getvalue()
              oldclose()
          f.close = newclose
          return f
     else:
          return old_open(name, mode, *args, **kwargs)

之后你就可以写:

f = open(":test:", "w")
f.write("This is a test\n")
f.close()

f = open(":test:")
print(f.read())

需要注意的是,这个例子非常简单,并没有处理所有的真实文件模式(比如追加模式,或者在读取模式下打开一个不存在的内存文件时抛出正确的异常),但对于简单的情况可能是有效的。

另外要注意的是,所有的内存文件会一直保留在内存中,除非你也修改了unlink

附注:我并不是说修改标准的打开方式或StringIO实例是个好主意,只是说你可以这么做 :-D

附注2:这种问题在操作系统层面上通过创建一个内存盘来解决得更好。这样你甚至可以调用外部程序,将它们的输出或输入重定向到这些文件中,并且你还可以获得完整的支持,包括并发访问、目录列表等等。

撰写回答