StringIO and compatibility with 'with' statement (context manager)

前端 未结 3 605
无人共我
无人共我 2020-12-23 16:41

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.

What

3条回答
  •  天命终不由人
    2020-12-23 16:54

    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.

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

    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)
    

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

提交回复
热议问题