在Python 3中重新打开一个已关闭的stringIO对象

时间:2015-05-28 15:03:06

标签: python-3.x file-io

因此,我创建了一个StringIO对象来将我的字符串视为文件:

>>> a = 'Me, you and them\n'
>>> import io
>>> f = io.StringIO(a)
>>> f.read(1)
'M'

然后我继续关闭'文件':

>>> f.close()
>>> f.closed
True

现在,当我再次尝试打开'文件'时,Python不允许我这样做:

>>> p = open(f)
Traceback (most recent call last):
  File "<pyshell#166>", line 1, in <module>
    p = open(f)
TypeError: invalid file: <_io.StringIO object at 0x0325D4E0>

有没有办法'重新打开'一个已关闭的StringIO对象?或者是否应该使用io.StringIO()方法再次声明?

谢谢!

4 个答案:

答案 0 :(得分:4)

内置open()创建一个文件对象(即流),但在您的示例中,f已经是一个流。 这就是你得到TypeError:无效文件

的原因

执行方法close()后,任何流操作都会引发ValueError。 文档没有提到如何重新打开封闭流。

如果您想稍后再次使用(重新打开),可能还需要关闭()流。

答案 1 :(得分:4)

我有一个不错的hack,我目前正在使用它进行测试(因为我的代码可以进行I / O操作,并且给StringIO一个不错的解决方法)。

如果这个问题是一次性的事情:

st = StringIO()
close = st.close
st.close = lambda: None
f(st)  # Some function which can make I/O changes and finally close st
st.getvalue()  # This is available now
close() # If you don't want to store the close function you can also:
StringIO.close(st)

如果这是重复发生的事情,则还可以定义一个上下文管理器:

@contextlib.contextmanager
def uncloseable(fd):
    """
    Context manager which turns the fd's close operation to no-op for the duration of the context.
    """
    close = fd.close
    fd.close = lambda: None
    yield fd
    fd.close = close

可以通过以下方式使用:

st = StringIO()
with uncloseable(st):
    f(st) 
# Now st is still open!!!

我希望这可以帮助您解决问题,如果没有,希望您能找到所需的解决方案。 注意:这对于其他类似文件的对象应该完全相同。

答案 2 :(得分:2)

不,没有办法重新打开io.StringIO对象。相反,只需使用io.StringIO()创建一个新对象。

close()对象上调用io.StringIO会丢弃“文件内容”数据,因此无论如何重新打开都无法访问该文件。

如果您需要数据,请在关闭前致电getvalue()

另请参见the StringIO documentation

  

调用close()方法时,将丢弃文本缓冲区。

在这里:

  

getvalue()

     

返回包含缓冲区全部内容的str。

答案 3 :(得分:0)

f.close()上将其从内存中删除。基本上,您正在做一个deref x,调用x;您正在寻找不存在的内存位置。

以下是您可以做的:

import io

a = 'Me, you and them\n'
f = io.StringIO(a)
f.read(1)
f.close()

# Put the text form a without the first char into StringIO.
p = io.StringIO(a[1:]).
# do some work with p.

我认为您的困惑来自将io.StringIO视为块设备上的文件。如果您使用open()而不是StringIO,那么在您的示例中您将是正确的,并且可以重新打开文件。 StringIO不是文件。这是内存中文件对象的想法。文件对象确实具有StringIO,但它实际上也存在于块设备上。 StringIO只是一个缓冲区,是其中存储数据的暂存区。当您调用open()时,会创建一个缓冲区,但是块设备上仍然有数据。

也许这就是您想要的

fo = open('f.txt','w+')
fo.write('Me, you and them\n')

fo.read(1)
fo.close()

# reopen the now closed file `f`
p = open('f.txt','r')
# do stuff with p
p.close()

在这里,我们正在将字符串写入块设备,因此,当我们关闭文件时,写入文件的信息将在关闭后保留。因为这是在运行progarm的目录中创建一个文件,所以最好给该文件扩展名。例如,您可以将文件命名为f.txt而不是f