我正在使用具有以下代码的异步项目(称为Broker
-see git)
proxies = asyncio.Queue()
broker = Broker(proxies)
tasks = asyncio.gather(broker.find(types = ['HTTPS'], strict = True, limit = 10),
self.storeProxies(proxies))
loop = asyncio.get_event_loop()
loop.run_until_complete(tasks)
其中self.storeProxies
是一个异步函数,其中包含
while True:
proxy = await proxies.get()
if proxy is None: break
self.proxies['http://{0}:{1}'.format(proxy.host, proxy.port)] = 1
但是,我认为它与Broker
部分无关(当然不确定)。
每次运行此代码时,在相当随机的成功次数之后,它会以[WinError 10038] An operation was attempted on something that is not a socket
失败。然后,我尝试进行一些研究,最终得到this answer。但是当尝试使用此代码时,出现此错误:
ValueError: loop argument must agree with Future
关于如何处理此问题的任何想法?
可能有用的详细信息:
OS:Windows 10(版本1809) Python版本:3.7.1
基于Mikhail Gerasimov的回答
async def storeProxies(self, proxies):
logger.info("IN IT!")
while True:
proxy = await proxies.get()
if proxy is None: break
self.proxies['http://{0}:{1}'.format(proxy.host, proxy.port)] = 1
async def getfetching(self, amount):
from proxybroker import Broker
proxies = asyncio.Queue()
broker = Broker(proxies)
return await asyncio.gather(
broker.find(
types = ['HTTP', 'HTTPS'],
strict = True,
limit = 10
),
self.storeProxies(proxies)
)
def fetchProxies(self, amount):
if os.name == 'nt':
loop = asyncio.SelectorEventLoop() # for subprocess' pipes on Windows
asyncio.set_event_loop(loop)
else:
loop = asyncio.get_event_loop()
loop.run_until_complete(self.getfetching(amount))
logger.info("FETCHING COMPLETE!!!!!!")
logger.info('Proxies: {}'.format(self.proxies))
其中fetchProxies
从另一个地方以一定的间隔被调用。第一次可以完美运行,但随后出现警告“失败”:
2019-04-06 21:04:21 [py.warnings] WARNING: d:\users\me\anaconda3\lib\site-packages\proxybroker\providers.py:78: DeprecationWarning: The object should be created from async function
headers=get_headers(), cookies=self._cookies, loop=self._loop
2019-04-06 21:04:21 [py.warnings] WARNING: d:\users\me\anaconda3\lib\site-packages\aiohttp\connector.py:730: DeprecationWarning: The object should be created from async function
loop=loop)
2019-04-06 21:04:21 [py.warnings] WARNING: d:\users\me\anaconda3\lib\site-packages\aiohttp\cookiejar.py:55: DeprecationWarning: The object should be created from async function
super().__init__(loop=loop)
之后是一个看起来像是无限循环的行为(硬输出什么也没有卡住)。值得注意的是,在全局导入Broker
时,在Gerasimov的示例中(在注释中)我也遇到了这种情况。最后,我开始看到隧道的光芒。
答案 0 :(得分:0)
看看这部分:
proxies = asyncio.Queue()
# ...
loop.run_until_complete(tasks)
asyncio.Queue()
创建时绑定到当前事件循环(默认事件循环或使用asyncio.set_event_loop()设置为当前事件循环)。通常只有循环对象绑定才能对其进行管理。如果更改当前循环,则应重新创建对象。许多其他asyncio
对象也是如此。
为确保每个对象都绑定到新的事件循环,最好在设置和运行新的事件循环后已经创建asyncio
相关的对象。看起来像这样:
async def main():
proxies = asyncio.Queue()
broker = Broker(proxies)
return await asyncio.gather(
broker.find(
types = ['HTTPS'],
strict = True,
limit = amount
),
self.storeProxies(proxies)
)
if os.name == 'nt':
loop = asyncio.ProactorEventLoop() # for subprocess' pipes on Windows
asyncio.set_event_loop(loop)
else:
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
有时(很少),您也必须在main()
内放置一些导入内容。
发生问题是因为您在fetchProxies
个调用之间更改了事件循环,但是Broker
仅导入了一次(Python缓存导入的模块)。
Reloading Broker
对我不起作用,因此我找不到比重用一次设置的事件循环更好的方法了。
替换此代码
if os.name == 'nt':
loop = asyncio.SelectorEventLoop() # for subprocess' pipes on Windows
asyncio.set_event_loop(loop)
else:
loop = asyncio.get_event_loop()
与此
if os.name == 'nt':
loop = asyncio.get_event_loop()
if not isinstance(loop, asyncio.SelectorEventLoop):
loop = asyncio.SelectorEventLoop() # for subprocess' pipes on Windows
asyncio.set_event_loop(loop)
else:
loop = asyncio.get_event_loop()
PS
顺便说一句,您不必首先这样做:
if os.name == 'nt':
loop = asyncio.SelectorEventLoop()
asyncio.set_event_loop(loop)
Windows已默认使用SelectorEventLoop
,并且不支持管道(doc)。