我有一个旧的函数,它接受一个文件名作为参数,并处理该文件内容的一些遗留代码。 代码的一个工作传真如下。
我想要做的就是没有写一些内容,我才能用这个传统功能产生的磁盘,所以我虽然我可以用StringIO
替代物理文件名来创建一个对象。 然而,这是不行的,因为你可以看到下面。
我以为StringIO
是去使用此方式。 谁能告诉我,如果存在,是不是磁盘上的文件,但可以通过传统的功能被视为这种参数使用该传统功能,并将它传递的东西呢? 遗留功能确实有with
上下文管理器做的工作filename
参数值。
我在谷歌遇到的一两件事是: 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
模块生成临时文件名来代替。
下面是一个使用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)
您还可以切换到由所提供的新的Python 3基础设施io
模块(在Python 2何时上市,3),其中io.BytesIO
是更强大的替代StringIO.StringIO
/ cStringIO.StringIO
。 这种对象不支持所使用的上下文管理器(但仍不能传递给open()
你可以定义自己的open函数
fopen = open
def open(fname,mode):
if hasattr(fname,"readlines"): return fname
else: return fopen(fname,mode)
然而,与想要呼叫__exit__其完成和StringIO的没有退出方法之后...
你可以自定义一个类与这个开放使用
class MyStringIO:
def __init__(self,txt):
self.text = txt
def readlines(self):
return self.text.splitlines()
def __exit__(self):
pass
这一个是基于Python的文档contextmanager
这只是StringIO的包装用简单的上下文,当调用exit函数,它会返回到屈服点,并妥善关闭StringIO的。 这避免了使临时文件的需要,但随着大字符串,这将仍然吃起来记忆,因为StringIO的缓冲区字符串。 它运作良好,你在哪里知道的字符串数据大多数情况下是不会很长
from contextlib import contextmanager
@contextmanager
def buildStringIO(strData):
from cStringIO import StringIO
try:
fi = StringIO(strData)
yield fi
finally:
fi.close()
然后,你可以这样做:
with buildStringIO('foobar') as f:
print(f.read()) # will print 'foobar'