![](/img/trans.png)
[英]Python3 error : AttributeError: module 'urllib' has no attribute 'request'
[英]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.