【发布时间】:2017-12-06 13:23:13
【问题描述】:
注意:未来的读者请注意,这个问题很老,格式化和编程很匆忙。给出的答案可能有用,但问题和代码可能没有。
大家好,
我无法理解 asyncio 和 aiohttp 并使两者协同工作。因为我不明白自己在做什么,所以我遇到了一个我不知道如何解决的问题。
我使用的是 Windows 10 64 位。
以下代码返回 Content-Type 标头中不包含“html”的页面列表。它是使用 asyncio 实现的。
import asyncio
import aiohttp
MAXitems = 30
async def getHeaders(url, session, sema):
async with session:
async with sema:
try:
async with session.head(url) as response:
try:
if "html" in response.headers["Content-Type"]:
return url, True
else:
return url, False
except:
return url, False
except:
return url, False
def check_urls_without_html(list_of_urls):
headers_without_html = set()
while(len(list_of_urls) != 0):
blockurls = []
print(len(list_of_urls))
items = 0
for num in range(0, len(list_of_urls)):
if num < MAXitems:
blockurls.append(list_of_urls[num - items])
list_of_urls.remove(list_of_urls[num - items])
items += 1
loop = asyncio.get_event_loop()
semaphoreHeaders = asyncio.Semaphore(50)
session = aiohttp.ClientSession()
data = loop.run_until_complete(asyncio.gather(*(getHeaders(url, session, semaphoreHeaders) for url in blockurls)))
for header in data:
if not header[1]:
headers_without_html.add(header)
return headers_without_html
list_of_urls= ['http://www.google.com', 'http://www.reddit.com']
headers_without_html = check_urls_without_html(list_of_urls)
for header in headers_without_html:
print(header[0])
当我使用太多 URL(即 2000)运行它时,有时它会返回类似这样的错误:
data = loop.run_until_complete(asyncio.gather(*(getHeaders(url, session, semaphoreHeaders) for url in blockurls)))
File "USER\AppData\Local\Programs\Python\Python36-32\lib\asyncio\base_events.py", line 454, in run_until_complete
self.run_forever()
File "USER\AppData\Local\Programs\Python\Python36-32\lib\asyncio\base_events.py", line 421, in run_forever
self._run_once()
File "USER\AppData\Local\Programs\Python\Python36-32\lib\asyncio\base_events.py", line 1390, in _run_once
event_list = self._selector.select(timeout)
File "USER\AppData\Local\Programs\Python\Python36-32\lib\selectors.py", line 323, in select
r, w, _ = self._select(self._readers, self._writers, [], timeout)
File "USER\AppData\Local\Programs\Python\Python36-32\lib\selectors.py", line 314, in _select
r, w, x = select.select(r, w, w, timeout)
ValueError: too many file descriptors in select()
我已经读到这个问题是由 Windows 的限制引起的。我还读到除了尝试使用更少的文件描述符之外,没有什么可以做的。
我看到人们使用 asyncio 和 aiohttp 推送数千个请求,但即使使用我的分块,我也无法推送 30-50 而不会出现此错误。
我的代码是否存在根本问题,还是 Windows 的固有问题?可以修复吗?可以增加select中允许的文件描述符的最大数量限制吗?
【问题讨论】:
标签: python python-3.x async-await python-asyncio aiohttp