python - 一次做更多的迭代python
问题描述
我有一个阻塞 for 循环,我尝试将套接字连接到服务器。我想做一个非阻塞循环,因为它需要很多时间,比如重叠连接。
这是我的示例代码:
import socket
for _ in range(100):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s.connect(('', 4444))
解决方案
正如 MLAlex 所建议的,使用 asyncio 库是有意义的。
这个怎么样,灵感来自asyncio 文档:
import asyncio
async def tcp_echo_client(message):
reader, writer = await asyncio.open_connection(
'127.0.0.1', 8888)
print(f'Send: {message!r}')
writer.write(message.encode())
await asyncio.sleep(randint(1,3))
data = await reader.read(100)
print(f'Received: {data.decode()!r}')
print('Close the connection')
writer.close()
await writer.wait_closed()
return data.decode()
async def main():
requests = [
tcp_echo_client(f"msg {i}") for i in range(10)
]
echoes = await asyncio.gather(*requests)
print(echoes)
asyncio.run(main())
例如,与这个回显服务器结合(需要三秒钟来回显一条消息):
import asyncio
async def handle_echo(reader, writer):
data = await reader.read(100)
message = data.decode()
addr = writer.get_extra_info('peername')
print(f"Received {message!r} from {addr!r}")
await asyncio.sleep(3)
print(f"Send: {message!r}")
writer.write(data)
await writer.drain()
print("Close the connection")
writer.close()
async def main():
server = await asyncio.start_server(
handle_echo, '127.0.0.1', 8888)
addr = server.sockets[0].getsockname()
print(f'Serving on {addr}')
async with server:
await server.serve_forever()
asyncio.run(main())
产生:
Send: 'msg 0'
Send: 'msg 1'
Send: 'msg 2'
Send: 'msg 3'
Send: 'msg 4'
Send: 'msg 5'
Send: 'msg 6'
Send: 'msg 7'
Send: 'msg 8'
Send: 'msg 9'
Received: 'msg 0'
Close the connection
Received: 'msg 1'
Close the connection
Received: 'msg 2'
Close the connection
Received: 'msg 3'
Close the connection
Received: 'msg 4'
Close the connection
Received: 'msg 5'
Close the connection
Received: 'msg 6'
Close the connection
Received: 'msg 7'
Close the connection
Received: 'msg 8'
Close the connection
Received: 'msg 9'
Close the connection
['msg 0', 'msg 1', 'msg 2', 'msg 3', 'msg 4', 'msg 5', 'msg 6', 'msg 7', 'msg 8', 'msg 9']
三秒左右,即只满足一个请求所需的时间
real 0m3,169s
user 0m0,044s
sys 0m0,084s
如果我们在服务器回复的时间上引入一些差异,我们可以看到客户端收到的结果是乱序的。例如在第 10 行:
await asyncio.sleep(randint(3,4))
那么客户端的输出变为:
(tih1) SO $ time python aio_cnx.py
Send: 'msg 0'
Send: 'msg 1'
Send: 'msg 2'
Send: 'msg 3'
Send: 'msg 4'
Send: 'msg 5'
Send: 'msg 6'
Send: 'msg 7'
Send: 'msg 8'
Send: 'msg 9'
Received: 'msg 1'
Close the connection
Received: 'msg 2'
Close the connection
Received: 'msg 3'
Close the connection
Received: 'msg 7'
Close the connection
Received: 'msg 8'
Close the connection
Received: 'msg 9'
Close the connection
Received: 'msg 0'
Close the connection
Received: 'msg 4'
Close the connection
Received: 'msg 5'
Close the connection
Received: 'msg 6'
Close the connection
['msg 0', 'msg 1', 'msg 2', 'msg 3', 'msg 4', 'msg 5', 'msg 6', 'msg 7', 'msg 8', 'msg 9']
real 0m4,135s
user 0m0,059s
sys 0m0,013s
推荐阅读
- python-3.6 - 在继续之前,如何确保 asyncio 未来已启动?
- rest - Api blockchain.com 注册返回 500 错误
- node.js - 在 Node.js 中将 tar 命令作为 child_process 运行
- hive - 有没有办法从这个 Hive 查询中提取一个子查询?
- php - Laravel 模型 - 如果数据库表不存在则返回 null
- html - 如何在css中取消设置填充颜色
- suitescript - 如何通过 suitescript 2.0 中的 url.resolveRecord() 导航到新记录?
- javascript - 从firebase读取布尔值的正确语法是什么?
- ansible - 有没有办法不使用 Ansible 在 Jinja2 模板中格式化数字?
- r - 输出excel文件时如何对R中的列进行颜色编码?