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

时间:2013-04-17 18:36:45

标签: python urllib

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

req = urllib.urlopen('http://example.com')

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

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

但是,在我的情况下,我有一个功能,我希望它对请求做出某些确定,然后返回该请求"不受伤害"这样它就可以再次阅读。

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

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

这是我唯一的选择吗?

2 个答案:

答案 0 :(得分: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)

如果代码实际上需要一个真正的Request对象(即调用isinstance来检查类型),那么继承Request,你甚至不必实现__getattr__

请注意,函数可能会检查确切的类(在这种情况下,您无法执行任何操作),或者,如果它是用C语言编写的,则使用C / API调用调用该方法(在这种情况下会被覆盖)方法不会被称为。)

答案 1 :(得分:2)

创建urllib2.Request的子类,使用cStringIO.StringIO来保存读取的内容。然后,您可以实现seek等等。实际上你可以只使用一个字符串,但这样做会更多。