我有一些带有遗留函数的遗留代码,该函数以文件名作为参数并处理文件内容。下面是该代码的有效传真。

我要做的是不必使用生成的某些内容将这些内容写入磁盘以使用此旧版功能,因此我可以使用StringIO代替物理文件名来创建对象。但是,这不起作用,如下所示。

我以为StringIO是解决此问题的方法。谁能告诉我是否有一种方法可以使用此旧版函数并将其传递给参数,该参数不是磁盘上的文件,但可以通过旧版函数进行处理?传统函数的确让with上下文管理器对filename参数值进行了处理。

我在Google中遇到的一件事是:http://bugs.python.org/issue1286,但这并没有帮助我...

代码

from pprint import pprint
import StringIO

    # Legacy Function
def processFile(filename):
    with open(filename, 'r') as fh:
        return fh.readlines()

    # This works
print 'This is the output of FileOnDisk.txt'
pprint(processFile('c:/temp/FileOnDisk.txt'))
print

    # This fails
plink_data = StringIO.StringIO('StringIO data.')
print 'This is the error.'
pprint(processFile(plink_data))

输出

这是FileOnDisk.txt的输出:
['This file is on disk.\n']

这是错误:

Traceback (most recent call last):
  File "C:\temp\test.py", line 20, in <module>
    pprint(processFile(plink_data))
  File "C:\temp\test.py", line 6, in processFile
    with open(filename, 'r') as fh:
TypeError: coercing to Unicode: need string or buffer, instance found

最佳答案

StringIO实例已经是一个打开的文件。另一方面,open命令仅采用文件名来返回打开的文件。 StringIO实例不适合作为文件名。

另外,您无需关闭StringIO实例,因此也无需将其用作上下文管理器。

如果您所有的旧代码都可以使用文件名,那么StringIO实例就不可行了。请使用 tempfile module生成一个临时文件名。

这是一个使用contextmanager来确保临时文件随后被清理的示例:

import os
import tempfile
from contextlib import contextmanager

@contextmanager
def tempinput(data):
    temp = tempfile.NamedTemporaryFile(delete=False)
    temp.write(data)
    temp.close()
    try:
        yield temp.name
    finally:
        os.unlink(temp.name)

with tempinput('Some data.\nSome more data.') as tempfilename:
    processFile(tempfilename)

您还可以切换到io模块提供的更新的Python 3基础结构(在Python 2和3中可用),其中 io.BytesIO StringIO.StringIO/cStringIO.StringIO的更强大的替代品。该对象确实支持用作上下文管理器(但仍然不能传递给open())。

关于python - StringIO和与 'with'语句的兼容性(上下文管理器),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11892623/

10-12 18:16