Wrap an open stream with io.TextIOWrapper

后端 未结 6 1668
太阳男子
太阳男子 2020-12-05 13:16

How can I wrap an open binary stream – a Python 2 file, a Python 3 io.BufferedReader, an io.BytesIO – in an io.TextIOWrapper

6条回答
  •  一整个雨季
    2020-12-05 13:53

    I needed this as well, but based on the thread here, I determined that it was not possible using just Python 2's io module. While this breaks your "Special treatment for file" rule, the technique I went with was to create an extremely thin wrapper for file (code below) that could then be wrapped in an io.BufferedReader, which can in turn be passed to the io.TextIOWrapper constructor. It will be a pain to unit test, as obviously the new code path can't be tested on Python 3.

    Incidentally, the reason the results of an open() can be passed directly to io.TextIOWrapper in Python 3 is because a binary-mode open() actually returns an io.BufferedReader instance to begin with (at least on Python 3.4, which is where I was testing at the time).

    import io
    import six  # for six.PY2
    
    if six.PY2:
        class _ReadableWrapper(object):
            def __init__(self, raw):
                self._raw = raw
    
            def readable(self):
                return True
    
            def writable(self):
                return False
    
            def seekable(self):
                return True
    
            def __getattr__(self, name):
                return getattr(self._raw, name)
    
    def wrap_text(stream, *args, **kwargs):
        # Note: order important here, as 'file' doesn't exist in Python 3
        if six.PY2 and isinstance(stream, file):
            stream = io.BufferedReader(_ReadableWrapper(stream))
    
        return io.TextIOWrapper(stream)
    

    At least this is small, so hopefully it minimizes the exposure for parts that cannot easily be unit tested.

提交回复
热议问题