gpt4 book ai didi

python - 在 io.TextIOWrapper 中包装 urllib3.HTTPResponse

转载 作者:行者123 更新时间:2023-12-03 20:21:49 24 4
gpt4 key购买 nike

我使用 AWS boto3返回一个 urllib3.response.HTTPResponse 实例的库.该响应是 io.IOBase 的子类因此表现为二进制文件。其read()方法返回 bytes实例。

现在,我需要解码 csv以这种方式接收的文件中的数据。我希望我的代码同时适用于 py2py3代码开销最小,所以我使用 backports.csv这依赖于 io.IOBase对象作为输入而不是 py2 的 file()对象。

第一个问题是 HTTPResponse产量 bytes CSV 文件的数据,我有 csv.reader预计 str数据。

>>> import io
>>> from backports import csv # actually try..catch statement here
>>> from mymodule import get_file

>>> f = get_file() # returns instance of urllib3.HTTPResponse
>>> r = csv.reader(f)
>>> list(r)
Error: iterator should return strings, not bytes (did you open the file in text mode?)

我试图包装 HTTPResponseio.TextIOWrapper并得到错误 'HTTPResponse' object has no attribute 'read1' .这是预期的,因为 TextIOWrapper旨在与 BufferedIOBase 一起使用对象,而不是 IOBase对象。它只发生在 python2TextIOWrapper 的实现因为它总是期望底层对象有 read1 ( source ),而 python3的实现检查 read1存在并回退到 read优雅地( source)。
>>> f = get_file()
>>> tw = io.TextIOWrapper(f)
>>> list(csv.reader(tw))
AttributeError: 'HTTPResponse' object has no attribute 'read1'

然后我尝试包装 HTTPResponseio.BufferedReader然后用 io.TextIOWrapper .我收到以下错误:
>>> f = get_file()
>>> br = io.BufferedReader(f)
>>> tw = io.TextIOWrapper(br)
>>> list(csv.reader(f))
ValueError: I/O operation on closed file.

经过一番调查,事实证明,该错误仅在文件不以 \n 结尾时发生。 .如果它确实以 \n 结尾那么问题不会发生,一切正常。
HTTPResponse 中有一些额外的逻辑用于关闭底层对象。 ( source ) 这似乎是导致问题的原因。

问题是:我怎样才能写我的代码
  • 在 python2 和 python3 上工作,最好不使用 try..catch 或依赖于版本的分支;
  • 正确处理表示为 HTTPResponse 的 CSV 文件不管它们是否以 \n 结尾或不?

  • 一种可能的解决方案是在 TextIOWrapper 周围制作自定义包装器。这将使 read()返回 b''当对象关闭而不是提升 ValueError .但是有没有更好的解决方案,没有这样的黑客?

    最佳答案

    看起来这是 urllib3.HTTPResponse 之间的接口(interface)不匹配和 file对象。在 this urllib3 issue #1305 中有描述.

    目前还没有修复,因此我使用了以下看似工作正常的包装器代码:

    class ResponseWrapper(io.IOBase):
    """
    This is the wrapper around urllib3.HTTPResponse
    to work-around an issue shazow/urllib3#1305.

    Here we decouple HTTPResponse's "closed" status from ours.
    """
    # FIXME drop this wrapper after shazow/urllib3#1305 is fixed

    def __init__(self, resp):
    self._resp = resp

    def close(self):
    self._resp.close()
    super(ResponseWrapper, self).close()

    def readable(self):
    return True

    def read(self, amt=None):
    if self._resp.closed:
    return b''
    return self._resp.read(amt)

    def readinto(self, b):
    val = self.read(len(b))
    if not val:
    return 0
    b[:len(val)] = val
    return len(val)

    并按如下方式使用它:
    >>> f = get_file()
    >>> r = csv.reader(ResponseWrapper(io.TextIOWrapper(io.BufferedReader(f))))
    >>> list(r)
    urllib3 提出了类似的修复。错误报告评论中的维护人员,但这将是一个重大更改,因此现在情况可能不会改变,所以我必须使用包装器(或者做一些可能更糟糕的猴子补丁)。

    关于python - 在 io.TextIOWrapper 中包装 urllib3.HTTPResponse,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47984230/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com