urllib.request:在不修改请求对象的情况下从中读取的任何方法?

Jor*_*ter 6 python urllib

给定一个标准urllib.request对象,检索如下:

req = urllib.urlopen('http://example.com')
Run Code Online (Sandbox Code Playgroud)

如果我通过via读取其内容req.read(),之后请求对象将为空.

然而,与普通的类文件对象不同,请求对象没有seek方法,因为我确信这是很好的理由.

但是,在我的情况下,我有一个函数,我希望它对请求做出某些确定,然后将该请求"无损"地返回,以便可以再次读取它.

我知道一个选择是重新请求它.但我希望能够避免为相同的网址和内容发出多个HTTP请求.

我能想到的唯一另一种选择是让函数返回提取内容和请求对象的元组,同时理解调用此函数的任何东西都必须以这种方式获取内容.

这是我唯一的选择吗?

Bak*_*riu 3

将缓存委托给一个StringIO对象(代码未测试,只是为了给出想法):

import urllib
from io import StringIO


class CachedRequest(object):
    def __init__(self, url):
        self._request = urllib.urlopen(url)
        self._content = None

    def __getattr__(self, attr):
        # if attr is not defined in CachedRequest, then get it from
        # the request object.
        return getattr(self._request, attr)

    def read(self):
        if self._content is None:
            content = self._request.read()
            self._content = StringIO()
            self._content.write(content)
            self._content.seek(0)
            return content
        else:
            return self._content.read()

    def seek(self, i):
        self._content.seek(i)
Run Code Online (Sandbox Code Playgroud)

如果代码实际上需要一个真实的Request对象(即调用isinstance来检查类型),则子类化Request,您甚至不必实现__getattr__.

请注意,函数可能会检查确切的类(在这种情况下您什么也做不了),或者如果它是用 C 编写的,则使用 C/API 调用来调用该方法(在这种情况下,重写的方法不会被称为)。