foreword
I shared a little bit of asynchronous concurrent code learned from the big guys when I was working before, and shared it with everyone, just copy and paste it.
import asyncio
import logging
import aiohttp
logging.basicConfig(format='[%(asctime)s] %(message)s', level=logging.INFO)
task_count = 0
async def async_get(url, out_type='text', **kwargs):
"""
模拟发送GET请求 异步实现
:param url:
:param out_type:
:param kwargs:
:return:
"""
return_info = {
}
try:
"""
设置超时时间(
total: 整个请求的超时时间,包括连接建立、请求发送、响应接收等所有阶段。如果在该时间内请求没有完成,就会抛出超时异常。在这个例子中,超时时间为10秒。
connect: 连接建立的超时时间。如果在该时间内连接没有建立成功,就会抛出超时异常。在这个例子中,连接建立的超时时间为2秒。
sock_connect: socket连接建立的超时时间。如果在该时间内socket连接没有建立成功,就会抛出超时异常。在这个例子中,socket
连接建立的超时时间为5秒。
sock_read: socket接收数据的超时时间。如果在该时间内没有接收到数据,就会抛出超时异常。在这个例子中,socket
接收数据的超时时间为5秒。
)
"""
timeout = aiohttp.ClientTimeout(total=10, connect=2, sock_connect=5, sock_read=5)
# 使用async with创建客户端(会自动关闭,所以我的main函数没有添加close,不然会报错)
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(limit=100, ssl=False),
timeout=timeout) as session:
async with session.get(url, **kwargs) as resp:
if resp and resp.status == 200:
if out_type == 'text':
data = await resp.text()
elif out_type == 'bytes':
data = await resp.content.read()
elif out_type == 'json':
data = await resp.json()
return_info['text'] = data
return_info['url'] = resp.url
return_info['headers'] = resp.headers
return_info['status'] = resp.status
return_info['cookies'] = resp.cookies
return return_info
except Exception as e:
logging.info(f"地址访问异常:{
url}-{
e}")
return return_info
async def async_post(url, out_type='json', **kwargs):
"""
模拟发送POST请求 异步实现
:param url:
:param out_type:
:param kwargs:
:return:
"""
return_info = {
}
try:
"""
设置超时时间(
total: 整个请求的超时时间,包括连接建立、请求发送、响应接收等所有阶段。如果在该时间内请求没有完成,就会抛出超时异常。在这个例子中,超时时间为10秒。
connect: 连接建立的超时时间。如果在该时间内连接没有建立成功,就会抛出超时异常。在这个例子中,连接建立的超时时间为2秒。
sock_connect: socket连接建立的超时时间。如果在该时间内socket连接没有建立成功,就会抛出超时异常。在这个例子中,socket
连接建立的超时时间为5秒。
sock_read: socket接收数据的超时时间。如果在该时间内没有接收到数据,就会抛出超时异常。在这个例子中,socket
接收数据的超时时间为5秒。
)
"""
timeout = aiohttp.ClientTimeout(total=10, connect=2, sock_connect=5, sock_read=5)
# 使用async with创建客户端(会自动关闭,所以我的main函数没有添加close,不然会报错)
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(limit=100, ssl=False),
timeout=timeout) as session:
async with session.post(url, **kwargs) as resp:
if resp and resp.status == 200:
if out_type == 'json':
data = await resp.text()
elif out_type == 'text':
data = await resp.json()
return_info['text'] = data
return_info['url'] = resp.url
return_info['headers'] = resp.headers
return_info['status'] = resp.status
return_info['cookies'] = resp.cookies
return return_info
except Exception as e:
logging.info(f"地址访问异常:{
url}-{
e}")
return return_info
async def get_url(url):
global task_count
res = await async_get(url)
# print(res)
task_count -= 1
return res
async def main():
global task_count
# 任务数量,可以从redis读取
urls = ['https://www.baidu.com/', 'https://www.baidu.com/', 'https://www.apple.com/'] * 5
# 并发数量
max_task_count = 10
while True:
# 控制并发
free_count = max_task_count - task_count
if free_count:
logging.info(
"系统当前正在执行任务数:{},未达到最大并发数:{},即将加载新的待执行任务...".format(task_count + 1,
max_task_count))
# 检查是否还有数据
if urls:
url = urls.pop()
task = asyncio.create_task(get_url(url))
# 运行一次增加一次并发任务量
task_count += 1
else:
logging.info('没有等待检测的url...')
await asyncio.sleep(1)
else:
await asyncio.sleep(1)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())