繁体   English   中英

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

[英]AttributeError: 'tuple' object has no attribute 'timeout' - urllib request in Python3

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

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)

根据要求,这是回溯:

AttributeError                            Traceback (most recent call last) <ipython-input-68-cb3f46b2da76> in <module>()
----> 1 urllib.request.urlopen(req)

C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\urllib\request.py in urlopen(url, data, timeout, cafile, capath, cadefault, context)
    221     else:
    222         opener = _opener
--> 223     return opener.open(url, data, timeout)
    224 
    225 def install_opener(opener):

C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\urllib\request.py in open(self, fullurl, data, timeout)
    515                 req.data = data
    516 
--> 517         req.timeout = timeout
    518         protocol = req.type
    519 

AttributeError: 'tuple' object has no attribute 'timeout'

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

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文档顶部的建议进行操作,那么所有这些都会容易urllib.request

另请参阅:建议将Requests 包用于更高级别的 HTTP 客户端接口。

有了 Requests,整个事情就变成了:

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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM