StringIO 和与 'with' 语句的兼容性(上下文管理器) [英] StringIO and compatibility with 'with' statement (context manager)

查看:61
本文介绍了StringIO 和与 'with' 语句的兼容性(上下文管理器)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些带有遗留函数的遗留代码,它将文件名作为参数并处理文件内容.代码的工作传真如下.

I have some legacy code with a legacy function that takes a filename as an argument and processes the file contents. A working facsimile of the code is below.

我想要做的是不必将我生成的一些内容写入磁盘以使用此遗留函数,所以我虽然我可以使用 StringIO 来创建一个对象来代替物理文件名.但是,这不起作用,如下所示.

What I want to do is not have to write to disk with some content that I generate in order to use this legacy function, so I though I could use StringIO to create an object in place of the physical filename. However, this does not work, as you can see below.

我认为 StringIO 是解决这个问题的方法.谁能告诉我是否有办法使用这个遗留函数并在参数中传递一些不是磁盘上的文件但可以被遗留函数视为这样的东西?遗留函数确实让 with 上下文管理器处理 filename 参数值.

I thought StringIO was the way to go with this. Can anyone tell me if there is a way to use this legacy function and pass it something in the argument that isn't a file on disk but can be treated as such by the legacy function? The legacy function does have the with context manager doing work on the filename parameter value.

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

The one thing I came across in google was: http://bugs.python.org/issue1286, but that didn't help me...

代码

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 实例不适合作为文件名.

A StringIO instance is an open file already. The open command, on the other hand, only takes filenames, to return an open file. A StringIO instance is not suitable as a filename.

此外,您不需要关闭 StringIO 实例,因此也不需要将其用作上下文管理器.

Also, you don't need to close a StringIO instance, so there is no need to use it as a context manager either.

如果您的所有遗留代码只能使用文件名,那么 StringIO 实例不是可行的方法.使用 tempfile 模块 来生成临时文件名.

If all your legacy code can take is a filename, then a StringIO instance is not the way to go. Use the tempfile module to generate a temporary filename instead.

下面是一个使用上下文管理器确保临时文件在之后被清理的示例:

Here is an example using a contextmanager to ensure the temp file is cleaned up afterwards:

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.BytesIOStringIO.StringIO/<代码>cStringIO.StringIO.此对象确实支持用作上下文管理器(但仍不能传递给 open()).

You can also switch to the newer Python 3 infrastructure offered by the io module (available in Python 2 and 3), where io.BytesIO is the more robust replacement for StringIO.StringIO / cStringIO.StringIO. This object does support being used as a context manager (but still can't be passed to open()).

这篇关于StringIO 和与 'with' 语句的兼容性(上下文管理器)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆