AttributeError:'tuple'对象没有属性'timeout'-Python3中的urllib请求

时间:2018-08-17 17:02:08

标签: python python-requests tuples urllib attributeerror

我正在使用urllib发出请求并获取一些返回的数据:

<base href="/project/example/" />

直到这里我都不会遇到任何问题:

queryURL = "https://hazards.fema.gov/gis/nfhl/rest/services/CSLF/Prelim_CSLF/MapServer/3/query"
params = urllib.parse.urlencode({'f': 'json', 'geometryType': 'esriGeometryPolygon', 'outFields': 'OBJECTID, SHAPE, CSLF_ID, Area_SF', 'returnGeometry': 'false'})

然后:

req = urllib.request.urlretrieve(queryURL, params)

在这一点上,我抛出一个错误-urllib.request.urlopen(req) ,我知道由于我格式化AttributeError: 'tuple' object has no attribute 'timeout'.变量的方式,它返回了一个不变的元组。我的问题是,如何解决这个问题,以便可以开始查看结果?

params

根据要求,这是回溯:

jsonResult = json.load(response)

1 个答案:

答案 0 :(得分:1)

核心问题是这段代码没有任何意义:

req = urllib.request.urlretrieve(queryURL, params)
urllib.request.urlopen(req)

urlretrieve为您发出网络请求,将结果保存在本地文件中,然后返回“元组(filename, headers)”。

您正在尝试将那对(filename, headers)传递给urlopen。但是urlopen不知道该怎么办;它需要一个URL字符串或一个Request对象,而一个(filename, headers)对都不是。

此外,还不清楚您想要想要做什么。您已经获取了请求并将结果保存在文件中。您为什么要再次获取相同的请求?

简单的答案是,如果不想使用urlretrieve。 (特别是因为它已被弃用……)只需执行以下操作:

response = urllib.request.urlopen(queryURL, params)

此外,请注意,我将urlopen的结果保存在一个变量中。如果您不这样做,那么您只是在发出请求并丢弃响应,这不是很有用。并且jsonResult = json.load(response)会给您一个NameError,因为您从未创建任何名为response的东西。


但是,您的代码仍然(至少)还有两个其他问题。

首先,正如urlencode的文档所述:

  

如果将结果字符串用作POST的数据……则应将其编码为字节,否则将导致TypeError

但是您没有那样做。

第二,如果要发送url编码的数据作为POST正文,则需要手动设置Content-Type标头,这样。

即使您弄错了,某些服务器也会正确猜测,但这并不是您应该依靠的。


最后,如果您按照urllib.request文档顶部的建议进行操作,那么所有这些操作将变得容易得多

  

另请参见:建议将Requests package用于更高级别的HTTP客户端界面。

有了请求,整个事情变成了:

queryURL = "https://hazards.fema.gov/gis/nfhl/rest/services/CSLF/Prelim_CSLF/MapServer/3/query"
params = {'f': 'json', 'geometryType': 'esriGeometryPolygon', 'outFields': 'OBJECTID, SHAPE, CSLF_ID, Area_SF', 'returnGeometry': 'false'}
jsonResult = requests.post(queryURL, data=params).json()