рдмрд╣реБрдд рд╕рдордп рдкрд╣рд▓реЗ,
рдЕрдЬрдЧрд░ 3.4 рдХрд╛ рдПрдХ рдирдпрд╛ рд╕рдВрд╕реНрдХрд░рдг
рдЪреИрдВрдЬ рдореЗрдВ
рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдЬрд┐рд╕рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ "рдЧреБрдбреА" рд╢рд╛рдорд┐рд▓ рдереЗред рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ
рдПрд╕рд┐рдВрдХреЛ рдореЙрдбреНрдпреВрд▓ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдиреЗрдЯрд╡рд░реНрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪрд╛ рд╣реИред рдХреЛрд░рдЯрд╛рдЗрдиреНрд╕ рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЛрдб рд╕рдордЭрдиреЗ рдФрд░ рдмрдирд╛рдП рд░рдЦрдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рд╣реИред
рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЯреАрд╕реАрдкреА (рдЗрдХреЛ) рд╕рд░реНрд╡рд░ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рдпрд╣ рджрд┐рдЦрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢
asyncio
рдХрд┐
asyncio
рдХреНрдпрд╛ рдЦрд╛рдпрд╛ рдЬрд╛рддрд╛
asyncio
рдФрд░ рдореИрдВ рдЗрд╕ рдореЙрдбреНрдпреВрд▓ рдХреЗ "рдШрд╛рддрдХ рджреЛрд╖" рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛
asyncio
, рдЕрд░реНрдерд╛рддреН рдПрдХ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ HTTP рд╕рд░реНрд╡рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдХрдореАред
рдкрд░рд┐рдЪрдп
рдПрдХ рдкреНрд░рддреНрдпрдХреНрд╖ рдкреНрд░рддрд┐рдпреЛрдЧреА рдФрд░ "рднрд╛рдИ"
рдмрд╡рдВрдбрд░ рдврд╛рдВрдЪрд╛ рд╣реИ, рдЬрд┐рд╕рдиреЗ рдЦреБрдж рдХреЛ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рд╣реИ рдФрд░ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд▓рд╛рдпрдХ рд▓реЛрдХрдкреНрд░рд┐рдпрддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, asyncore рд╕рд░рд▓, рдЕрдзрд┐рдХ рддрд╛рд░реНрдХрд┐рдХ рдФрд░ рд╡рд┐рдЪрд╛рд░рд╢реАрд▓ рджрд┐рдЦрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рдЖрд╢реНрдЪрд░реНрдп рдХреА рдмрд╛рдд рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдПрдХ рдорд╛рдирдХ рднрд╛рд╖рд╛ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВред
рдЖрдк рдХрд╣реЗрдВрдЧреЗ рдХрд┐ рдЖрдк рдкрд╣рд▓реЗ рдкрд╛рдпрдерди рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╕реЗрд╡рд╛рдПрдВ рд▓рд┐рдЦ рд╕рдХрддреЗ рдереЗ рдФрд░ рдЖрдк рд╕рд╣реА рд╣реЛрдВрдЧреЗред рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд▓рд┐рдП рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдФрд░ / рдпрд╛ рдХреЙрд▓рдмреИрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рд╢реИрд▓реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдЖрд╡рд╢реНрдпрдХ рдерд╛ред рдкрд╛рдЗрдерди рдХреЗ рдЗрд╕ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдкреВрд░реНрдгрддрд╛ рдХреЗ рд▓рд┐рдП рд▓рд╛рдпрд╛ рдЧрдпрд╛ рдХреЛрд░рдЯрд╛рдЗрди рдЕрд╡рдзрд╛рд░рдгрд╛, рдЖрдкрдХреЛ рдХреЗрд╡рд▓ рдорд╛рдирдХ рднрд╛рд╖рд╛ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреА рдХреНрд╖рдорддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд░реИрдЦрд┐рдХ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдореИрдВ рддреБрд░рдВрдд рдПрдХ рдЖрд░рдХреНрд╖рдг рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдЬреЛ рдореИрдВрдиреЗ рд▓рд┐рдирдХреНрд╕ рдХреЗ рддрд╣рдд рдпрд╣ рд╕рдм рд▓рд┐рдЦрд╛ рдерд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рдШрдЯрдХ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рд╣реИрдВ рдФрд░ рд╡рд┐рдВрдбреЛрдЬ рдХреЗ рддрд╣рдд рднреА рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рд▓реЗрдХрд┐рди рдкрд╛рдпрдерди 3.4 рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
EchoServer
рдЗрдХреЛ рд╕рд░реНрд╡рд░ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдорд╛рдирдХ рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣
рдирд┐рдореНрди-рд╕реНрддрд░реАрдп рдПрдкреАрдЖрдИ "рдЯреНрд░рд╛рдВрд╕рдкреЛрд░реНрдЯ рдФрд░ рдкреНрд░реЛрдЯреЛрдХреЙрд▓" рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИред "рд░реЛрдЬрдорд░реНрд░рд╛" рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП,
рдЙрдЪреНрдЪ-рд╕реНрддрд░реАрдп рдПрдкреАрдЖрдИ "рд╕реНрдЯреНрд░реАрдо" рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢
рдХреА рдЬрд╛рддреА рд╣реИред рдЗрд╕рдореЗрдВ рдХреЛрдИ рдирдореВрдирд╛ рдЯреАрд╕реАрдкреА рд╕рд░реНрд╡рд░ рдХреЛрдб рдирд╣реАрдВ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдирд┐рдореНрди-рд╕реНрддрд░реАрдп рдПрдкреАрдЖрдИ рд╕реЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рджреЛрдиреЛрдВ рдореЙрдбреНрдпреВрд▓ рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЯреАрд╕реАрдкреА рд╕рд░реНрд╡рд░ рд▓рд┐рдЦрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред
import asyncio import logging import concurrent.futures @asyncio.coroutine def handle_connection(reader, writer): peername = writer.get_extra_info('peername') logging.info('Accepted connection from {}'.format(peername)) while True: try: data = yield from asyncio.wait_for(reader.readline(), timeout=10.0) if data: writer.write(data) else: logging.info('Connection from {} closed by peer'.format(peername)) break except concurrent.futures.TimeoutError: logging.info('Connection from {} closed by timeout'.format(peername)) break writer.close() if __name__ == '__main__': loop = asyncio.get_event_loop() logging.basicConfig(level=logging.INFO) server_gen = asyncio.start_server(handle_connection, port=2007) server = loop.run_until_complete(server_gen) logging.info('Listening established on {0}'.format(server.sockets[0].getsockname())) try: loop.run_forever() except KeyboardInterrupt: pass
рд╕рдм рдХреБрдЫ рдХрд╛рдлреА рд╕реНрдкрд╖реНрдЯ рд╣реИ, рд▓реЗрдХрд┐рди рдХреБрдЫ рдмрд╛рд░реАрдХрд┐рдпрд╛рдВ рд╣реИрдВ рдЬреЛ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИрдВред
server_gen = asyncio.start_server(handle_connection, port=2007) server = loop.run_until_complete(server_gen)
рдкрд╣рд▓реА рдкрдВрдХреНрддрд┐ рд╕рд░реНрд╡рд░ рдХреЛ рд╕реНрд╡рдпрдВ рдирд╣реАрдВ рдмрдирд╛рддреА рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рдЬрдирд░реЗрдЯрд░, рдЬрд┐рд╕реЗ рдЬрдм
asyncio
рдкрд╣рд▓реА рдмрд╛рд░ рдПрдХреНрд╕реЗрд╕ рдХрд░рддрд╛ рд╣реИ рдФрд░
asyncio
рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЯреАрд╕реАрдкреА рд╕рд░реНрд╡рд░ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдЖрд░рдВрдн рдХрд░рддрд╛ рд╣реИред рджреВрд╕рд░реА рдкрдВрдХреНрддрд┐ рдЗрд╕ рддрд░рд╣ рдХреА рдЕрдкреАрд▓ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИред
try: data = yield from asyncio.wait_for(reader.readline(), timeout=10.0) if data: writer.write(data) else: logging.info('Connection from {} closed by peer'.format(peername)) break except concurrent.futures.TimeoutError: logging.info('Connection from {} closed by timeout'.format(peername)) break
рдлрдВрдХреНрд╢рди-
reader.readline()
рдЗрдирдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рд╕реЗ рдбреЗрдЯрд╛ рдХреА рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд░реАрдбрд┐рдВрдЧ рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдбреЗрдЯрд╛ рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдирд╛ рд╕рдордп рдореЗрдВ рд╕реАрдорд┐рдд рдирд╣реАрдВ рд╣реИ, рдЕрдЧрд░ рдЖрдкрдХреЛ рдЗрд╕реЗ рдЯрд╛рдЗрдордЖрдЙрдЯ рджреНрд╡рд╛рд░рд╛ рд░реЛрдХрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ
asyncio.wait_for()
рдореЗрдВ coroutine рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдХреЛ рд▓рдкреЗрдЯрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рд╕реЗрдХрдВрдб рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕рдордп рдЕрдВрддрд░рд╛рд▓ рдмреАрдд рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж,
concurrent.futures.TimeoutError
рдЕрдкрд╡рд╛рдж рдХреЛ рдЙрдард╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рд╕реЗ рдЖрд╡рд╢реНрдпрдХ рд░реВрдк рд╕реЗ рд╕рдВрднрд╛рд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдпрд╣
reader.readline()
рдХрд┐
reader.readline()
рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдЧреИрд░-рд░рд┐рдХреНрдд рдорд╛рди рджреЗрддрд╛ рд╣реИ, рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЕрдиреНрдпрдерд╛, рдХреНрд▓рд╛рдЗрдВрдЯ рджреНрд╡рд╛рд░рд╛ рдХрдиреЗрдХреНрд╢рди рдХрд╛рдЯ рджрд┐рдП рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж (рд╕рд╣рдХрд░реНрдореА рджреНрд╡рд╛рд░рд╛ рдХрдиреЗрдХреНрд╢рди рд░реАрд╕реЗрдЯ), рдЦрд╛рд▓реА рдорд╛рди рдкрдврд╝рдиреЗ рдФрд░ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдЕрдирд┐рд╢реНрдЪрд┐рдд рдХрд╛рд▓ рддрдХ рдЬрд╛рд░реА рд░рд╣реЗрдЧрд╛ред
рд▓реЗрдХрд┐рди OOP рдХрд╛ рдХреНрдпрд╛?
OOP рднреА рдареАрдХ рд╣реИред рдпрд╣ @ asyncio.coroutine рдбреЗрдХреЛрд░реЗрдЯрд░ рдореЗрдВ coroutine рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рд▓рдкреЗрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред рдПрдкреАрдЖрдИ рдореЗрдВ рдХреЙрд░рдЖрдЙрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдХреМрди рд╕реЗ рдХрд╛рд░реНрдп рдЪрд▓рддреЗ рд╣реИрдВ, рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╣реИред рдиреАрдЪреЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬреЛ рдЗрдХреЛ рд╕реЗрд╡рд░ рд╡рд░реНрдЧ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред
import asyncio import logging import concurrent.futures class EchoServer(object): """Echo server class""" def __init__(self, host, port, loop=None): self._loop = loop or asyncio.get_event_loop() self._server = asyncio.start_server(self.handle_connection, host=host, port=port) def start(self, and_loop=True): self._server = self._loop.run_until_complete(self._server) logging.info('Listening established on {0}'.format(self._server.sockets[0].getsockname())) if and_loop: self._loop.run_forever() def stop(self, and_loop=True): self._server.close() if and_loop: self._loop.close() @asyncio.coroutine def handle_connection(self, reader, writer): peername = writer.get_extra_info('peername') logging.info('Accepted connection from {}'.format(peername)) while not reader.at_eof(): try: data = yield from asyncio.wait_for(reader.readline(), timeout=10.0) writer.write(data) except concurrent.futures.TimeoutError: break writer.close() if __name__ == '__main__': logging.basicConfig(level=logging.DEBUG) server = EchoServer('127.0.0.1', 2007) try: server.start() except KeyboardInterrupt: pass
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдкрд╣рд▓реЗ рдФрд░ рджреВрд╕рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдХреЛрдб рд░реИрдЦрд┐рдХ рдФрд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкрдардиреАрдп рд╣реИред рдФрд░ рджреВрд╕рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдХреЛрдб рдПрдХ рд╕реНрд╡-рдирд┐рд╣рд┐рдд рд╡рд░реНрдЧ рдореЗрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред
HTTP рд╕рд░реНрд╡рд░
рдЗрд╕ рд╕рдм рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рдмрд╛рдж, рдЕрдиреИрдЪреНрдЫрд┐рдХ рд░реВрдк рд╕реЗ рдХреБрдЫ рдФрд░ рдкрд░реНрдпрд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЗрдЪреНрдЫрд╛ рд╣реЛрддреА рд╣реИред
asyncio
рдореЙрдбреНрдпреВрд▓ рд╣рдореЗрдВ рдРрд╕рд╛ рдЕрд╡рд╕рд░ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,
tornado
, рдПрдХ HTTP рд╕рд░реНрд╡рд░ рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рд╡реЗ рдХрд╣рддреЗ рд╣реИрдВ, рдЗрд╕ рдЪреВрдХ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдирд╣реАрдВ рдХрд░рдирд╛ рдПрдХ рдкрд╛рдк рд╣реИ :)
рдЕрдкрдиреЗ рд╕рднреА рд╡рд░реНрдЧреЛрдВ рдЬреИрд╕реЗ рдХрд┐ HTTPRequest, рдЗрддреНрдпрд╛рджрд┐ рдХреЗ рд╕рд╛рде рдЦрд░реЛрдВрдЪ рд╕реЗ рдПрдХ рд╕рдВрдкреВрд░реНрдг HTTP рд╕рд░реНрд╡рд░ рд▓рд┐рдЦрдирд╛ рдПрдХ рдЦреЗрд▓ рдирд╣реАрдВ рд╣реИ, рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ WSGI рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рдЯрди рд╣реИрдВред рдЙрди рд▓реЛрдЧреЛрдВ рдХреЛ рдкрддрд╛ рд╣реИ рдХрд┐ WSGI рдПрдХ рддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╣реИред рдпрд╣ рд╕рдЪ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк environ рдФрд░ рдЕрдиреБрд░реЛрдз рдирд┐рдХрд╛рдп рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдХреЛ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред WSGI рдХреЗ рдкрд░рд┐рдгрд╛рдо рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдЬрдирд░реЗрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдиреБрд╢рдВрд╕рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрд╣
asyncio
рдореЗрдВ рдЗрд╕реНрддреЗрдорд╛рд▓ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ
asyncio
рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЗ рд╕рд╛рде рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдлрд┐рдЯ рдмреИрдарддрд╛ рд╣реИред
рд╕рд╛рдордЧреНрд░реА рдХреА рд╡рд╛рдкрд╕реА рдХреЗ рд╕рд╛рде рд╕рдм рдХреБрдЫ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдЪреМрдЦрдЯреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ
рдмреЛрддрд▓ рд╣реИ ред рдЗрд╕рд▓рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд╣реАрдВ рдмрд▓реНрдХрд┐ рдЬрдирд░реЗрдЯрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рднрд╛рдЧреЛрдВ рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рджреЗрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдореИрдВрдиреЗ рдЗрд╕реЗ рд╡рд┐рдХрд╕рд┐рдд WSGI рд╕рд░реНрд╡рд░ рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЪреБрдирд╛ рдФрд░ рдкрд░рд┐рдгрд╛рдо рд╕реЗ рд╕рдВрддреБрд╖реНрдЯ рдерд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдбреЗрдореЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдХрдИ рдХреНрд▓рд╛рдЗрдВрдЯ рдХрдиреЗрдХреНрд╢рдиреЛрдВ рдХреЛ рдмрдбрд╝реА рдлрд╝рд╛рдЗрд▓ рджреЗрдиреЗ рдореЗрдВ рдХрд╛рдлреА рд╕рдХреНрд╖рдо рдерд╛ред
рдореИрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐
рдореЗрд░реЗ рдЧрд┐рддреБрдм рдкрд░ рдХреНрдпрд╛ рд╣реБрдЖред рди рддреЛ рдкрд░реАрдХреНрд╖рдг, рдФрд░ рди рд╣реА рдкреНрд░рд▓реЗрдЦрди рдЕрднреА рддрдХ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдмреЛрддрд▓ рдХреЗ рдврд╛рдВрдЪреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдбреЗрдореЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╣реИред рдпрд╣ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдлрд╛рдЗрд▓реЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЪрдпрдирд┐рдд рдПрдХ рдХреЛ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдореЛрдб рдореЗрдВ рджреЗрддрд╛ рд╣реИ, рдЖрдХрд╛рд░ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ред рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдЖрдк рдлрд┐рд▓реНрдореЛрдВ рдХреА рдЗрд╕ рд╕реВрдЪреА рдореЗрдВ рдлреЗрдВрдХрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдПрдХ рдЫреЛрдЯреА рд╡реАрдбрд┐рдпреЛ рд╣реЛрд╕реНрдЯрд┐рдВрдЧ рдЖрдпреЛрдЬрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ :)
рдореИрдВ
рдЪреЗрд░реАрдкреА рд╡рд┐рдХрд╛рд╕ рдЯреАрдо рдХреЛ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдзрдиреНрдпрд╡рд╛рдж рдХрд╣рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛, рдореИрдВрдиреЗ рдЕрдХреНрд╕рд░ рдЙрдирдХреЗ рдХреЛрдб рдХреЛ рджреЗрдЦрд╛ рдФрд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХреБрдЫ рд▓рд┐рдпрд╛ рддрд╛рдХрд┐ "рдЕрдкрдиреА рдЦреБрдж рдХреА рдмрд╛рдЗрдХ" рдХреЗ рд╕рд╛рде рди рдЖрдКрдВред
рдирдореВрдирд╛ рдЖрд╡реЗрджрди рджреЗрдЦреЗрдВ import bottle import os.path from os import listdir from bottle import route, template, static_file root = os.path.abspath(os.path.dirname(__file__)) @route('/') def index(): tmpl = """<!DOCTYPE html> <html> <head><title>Bottle of Aqua</title></head> </body> <h3>List of files:</h3> <ul> % for item in files: <li><a href="/files/{{item}}">{{item}}</a></li> % end </ul> </body> </html> """ files = [file_name for file_name in listdir(os.path.join(root, 'files')) if os.path.isfile(os.path.join(root, 'files', file_name))] return template(tmpl, files=files) @route('/files/<filename>') def server_static(filename): return static_file(filename, root=os.path.join(root,'files')) class AquaServer(bottle.ServerAdapter): """Bottle server adapter""" def run(self, handler): import asyncio import logging from aqua.wsgiserver import WSGIServer logging.basicConfig(level=logging.ERROR) loop = asyncio.get_event_loop() server = WSGIServer(handler, loop=loop) server.bind(self.host, self.port) try: loop.run_forever() except KeyboardInterrupt: pass
рдбрдмреНрд▓реВрдПрд╕рдЬреАрдЖрдИ рд╕рд░реНрд╡рд░ рдХреЛрдб рд▓рд┐рдЦрддреЗ рд╕рдордп, рдореИрдВрдиреЗ рдХрд┐рд╕реА рднреА рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдХреЛ рдиреЛрдЯрд┐рд╕ рдирд╣реАрдВ рдХрд┐рдпрд╛, рдЬрд┐рд╕реЗ
asyncio
рдореЙрдбреНрдпреВрд▓ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдард╣рд░рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдПрдХрдорд╛рддреНрд░ рдХреНрд╖рдг, рдпрд╣ рдмреНрд░рд╛рдЙрдЬрд╝рд░реЛрдВ рдХреА рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХреНрд░реЛрдо) рдЕрдиреБрд░реЛрдз рдХреЛ рд░реАрд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдЧрд░ рдпрд╣ рджреЗрдЦрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдмрдбрд╝реА рдлрд╝рд╛рдЗрд▓ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрддрд╛ рд╣реИред рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдпрд╣ рдмрдбрд╝реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рдЕрдиреБрдХреВрд▓рд┐рдд рддрд░реАрдХреЗ рд╕реЗ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдХреНрдпреЛрдВрдХрд┐ рдЙрд╕рдХреЗ рдмрд╛рдж рдЕрдиреБрд░реЛрдз рджреЛрд╣рд░рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рд╕реНрд╡реАрдХрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ рдЦрд╛рд░рд┐рдЬ рдЕрдиреБрд░реЛрдз рдПрдХ
ConnectionResetError
рдЕрдкрд╡рд╛рдж рдХреЛ рдлреЗрдВрдХ рджреЗрддрд╛ рд╣реИ рдпрджрд┐ рдЙрд╕ рдкрд░ рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб рдкрд╣рд▓реЗ рд╕реЗ рд╣реА
StreamWriter.write()
рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рд╢реБрд░реВ рд╣реЛ рдЧрдпрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдХреЛ
StreamWriter.close()
рд╕рд╛рде рд╕рдВрднрд╛рд▓рд╛ рдФрд░ рдмрдВрдж рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдЙрддреНрдкрд╛рджрдХрддрд╛
рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ
рдШреЗрд░рд╛рдмрдВрджреА рдХреА рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХреЛ рдЪреБрдирд╛ред рдкрд░реАрдХреНрд╖рдг рд╡рд┐рд╖рдп "рд╣рдорд╛рд░реЗ рд░реЛрдЧреА" рдереЗ (рдЙрд░реНрдл рдПрдХреНрд╡рд╛ :) рдПрдХ
bottle
рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдореЗрдВ, рдПрдХ
bottle
рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдлреА рд▓реЛрдХрдкреНрд░рд┐рдп
рд╡реЗрдЯреНрд░реЗрд╕ рдбрдмреНрд▓реВрдПрд╕рдЬреАрдЖрдИ рд╕рд░реНрд╡рд░ рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЯреЙрд░рдиреЗрдбреЛ рднреАред рдПрдХ рдРрдк рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдмрд╕реЗ рдЫреЛрдЯрд╛ рд╕рдВрднрд╡ рд╣реЗрд▓реЛрд╡рд░реНрдб рдерд╛ред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдХрд┐рдП рдЧрдП рдкрд░реАрдХреНрд╖рдг: 100 рдФрд░ 1000 рдПрдХ рд╕рд╛рде рдХрдиреЗрдХреНрд╢рди; 13 рдмрд╛рдЗрдЯреНрд╕ рдФрд░ рдХрд┐рд▓реЛрдмрд╛рдЗрдЯ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдХреА рдЕрд╡рдзрд┐ 10 рд╕реЗрдХрдВрдб; 13 рдореЗрдЧрд╛рдмрд╛рдЗрдЯ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдХреА рдЕрд╡рдзрд┐ 60 рд╕реЗрдХрдВрдб; рд▓реМрдЯреЗ рдбреЗрдЯрд╛ рдХреЗ рдЖрдХрд╛рд░ рдХреЗ рд▓рд┐рдП рддреАрди рд╡рд┐рдХрд▓реНрдк, рдХреНрд░рдорд╢рдГ 13 рдмрд╛рдЗрдЯреНрд╕, 13 рдХрд┐рд▓реЛрдмрд╛рдЗрдЯ рдФрд░ 13 рдореЗрдЧрд╛рдмрд╛рдЗрдЯред рдиреАрдЪреЗ рдкрд░рд┐рдгрд╛рдо рд╣реИ:
100 рд╕реБрдЧрдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛
| 13 рдмреА (10 рд╕реЗрдХрдВрдб)
| 13 Kb (10 рд╕реЗрдХрдВрдб)
| 13 рдПрдордмреА (60 рд╕реЗрдХрдВрдб)
|
---|
рд▓рд╛рдн рдЙрдард╛рдПрдВред
| рдЯреНрд░рд╛рдВрд╕ / рд╕реЗрдХрдВрдб
| рд▓рд╛рдн рдЙрдард╛рдПрдВред
| рдЯреНрд░рд╛рдВрд╕ / рд╕реЗрдХрдВрдб
| рд▓рд╛рдн рдЙрдард╛рдПрдВред
| рдЯреНрд░рд╛рдВрд╕ / рд╕реЗрдХрдВрдб
|
рдПрдХреНрд╡рд╛ + рдмреЛрддрд▓
| 100.0%
| 835.24
| 100.0%
| 804.49
| 99.9%
| 26.28
|
рд╡реЗрдЯреНрд░реЗрд╕ + рдмреВрдЯрд▓реЗ
| 100.0%
| 707.24
| 100.0%
| 642.03
| 100.0%
| 8.67
|
рдмрд╡рдВрдбрд░
| 100.0%
| 2282.45
| 100.0%
| 2071.27
| 100.0%
| 15.78
|
1000 рд╕реБрдЧрдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛
| 13 рдмреА (10 рд╕реЗрдХрдВрдб)
| 13 Kb (10 рд╕реЗрдХрдВрдб)
| 13 рдПрдордмреА (60 рд╕реЗрдХрдВрдб)
|
---|
рд▓рд╛рдн рдЙрдард╛рдПрдВред
| рдЯреНрд░рд╛рдВрд╕ / рд╕реЗрдХрдВрдб
| рд▓рд╛рдн рдЙрдард╛рдПрдВред
| рдЯреНрд░рд╛рдВрд╕ / рд╕реЗрдХрдВрдб
| рд▓рд╛рдн рдЙрдард╛рдПрдВред
| рдЯреНрд░рд╛рдВрд╕ / рд╕реЗрдХрдВрдб
|
рдПрдХреНрд╡рд╛ + рдмреЛрддрд▓
| 99.9%
| 800.41
| 99.9%
| 777.15
| 60,2%
| 26.24
|
рд╡реЗрдЯреНрд░реЗрд╕ + рдмреВрдЯрд▓реЗ
| 94.9%
| 689.23
| 99.9%
| 621.03
| 37,5%
| 8.89
|
рдмрд╡рдВрдбрд░
| 100.0%
| 1239.88
| 100.0%
| 978.73
| 55.7%
| 14.51
|
рдореИрдВ рдХреНрдпрд╛ рдХрд╣ рд╕рдХрддрд╛ рд╣реВрдВ? рдмрд╡рдВрдбрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЖрдЧреЗ рдмрдврд╝рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди "рд╣рдорд╛рд░рд╛ рд░реЛрдЧреА" рдмрдбрд╝реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдкрд░ рдЖрдЧреЗ рд▓рдЧрддрд╛ рд╣реИ рдФрд░ рдЕрдзрд┐рдХ рдХрдиреЗрдХреНрд╢рдиреЛрдВ рдкрд░ рд╕рд╛рдкреЗрдХреНрд╖ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд┐рдпрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЙрдиреНрд╣реЛрдВрдиреЗ рдЖрддреНрдорд╡рд┐рд╢реНрд╡рд╛рд╕ рд╕реЗ рд╡реЗрдЯреНрд░реЗрд╕ (рдЗрд╕рдХреА рдЪрд╛рд░ рдмрд╛рд▓ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХреЛрд░ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде) рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд┐рдпрд╛, рдЬреЛ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рдмреАрдЪ рдЦрд░рд╛рдм рддрд░реАрдХреЗ рд╕реЗ рдирд╣реАрдВ рд╣реИред рдореИрдВ рдпрд╣ рдирд╣реАрдВ рдХрд╣ рд╕рдХрддрд╛ рдХрд┐ рдореЗрд░рд╛ рдкрд░реАрдХреНрд╖рдг 100% рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╢рд╛рдпрдж рдПрдХ рдореВрд▓реНрдпрд╛рдВрдХрди рдХреЗ рд░реВрдк рдореЗрдВ рдлрд┐рдЯ рд╣реЛрдЧрд╛ред
рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛: рдореИрдВрдиреЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╢рд░реАрд░ рдХреЗ 13 рдореЗрдЧрд╛рдмрд╛рдЗрдЯ рдХреЗ рд▓рд┐рдП рдЕрдЬреАрдм рд╕рдВрдЦреНрдпрд╛ рджреЗрдЦреАред рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, 10 рд╕реЗрдХрдВрдб рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рд╕рдВрднрд╡рддрдпрд╛ рд╢реБрд░реВ рдирд╣реАрдВ рд╣реБрдЖ :) рдЬреЛ рд╕рдВрдЦреНрдпрд╛ рдореБрдЭреЗ 60 рд╕реЗрдХрдВрдб рдХреА рдкрд░реАрдХреНрд╖рдг рдЕрд╡рдзрд┐ рдХреЗ рд╕рд╛рде рдорд┐рд▓реА рдереА, рдЙрд╕рдХреЗ рд▓рд┐рдП рд╕рд╣реА рд╣реИредрджреВрд╕рд░реА рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рдЕрдВрддрд┐рдо рд╕реНрддрдВрдн рдХреЗ рд▓рд┐рдП рдШреЗрд░рд╛рдмрдВрджреА рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдЙрджрд╛рд╣рд░рдг рдФрд░ рдкреВрд░реНрдг рдкрд░рд┐рдгрд╛рдо $ siege -c 1000 -b -t 60S http://127.0.0.1:5000/ ** SIEGE 2.70 ** Preparing 1000 concurrent users for battle. Transactions: 1570 hits Availability: 60.18 % Elapsed time: 59.84 secs Data transferred: 20410.00 MB Response time: 5.56 secs Transaction rate: 26.24 trans/sec Throughput: 341.08 MB/sec Concurrency: 145.80 Successful transactions: 1570 Failed transactions: 1039 Longest transaction: 20.44 Shortest transaction: 0.00 $ siege -c 1000 -b -t 60S http://127.0.0.1:5001/ ** SIEGE 2.70 ** Preparing 1000 concurrent users for battle. The server is now under siege... Lifting the server siege... done. Transactions: 526 hits Availability: 37.49 % Elapsed time: 59.20 secs Data transferred: 6838.00 MB Response time: 16.05 secs Transaction rate: 8.89 trans/sec Throughput: 115.51 MB/sec Concurrency: 142.58 Successful transactions: 526 Failed transactions: 877 Longest transaction: 42.43 Shortest transaction: 0.00 $ siege -c 1000 -b -t 60S http://127.0.0.1:5002/ ** SIEGE 2.70 ** Preparing 1000 concurrent users for battle. The server is now under siege... Lifting the server siege... done. Transactions: 857 hits Availability: 55.65 % Elapsed time: 59.07 secs Data transferred: 11141.00 MB Response time: 20.14 secs Transaction rate: 14.51 trans/sec Throughput: 188.61 MB/sec Concurrency: 292.16 Successful transactions: 857 Failed transactions: 683 Longest transaction: 51.19 Shortest transaction: 3.26
Outro
рдПрдХ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╡реЗрдм рд╕рд░реНрд╡рд░ рдЬреЛ
asyncio
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░
asyncio
рд╣реИ рдЙрд╕реЗ рдЬреАрд╡рди рдХрд╛ рдЕрдзрд┐рдХрд╛рд░ рд╣реИред рдЧрдВрднреАрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдРрд╕реЗ рд╕рд░реНрд╡рд░реЛрдВ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рдмрд╣реБрдд рдЬрд▓реНрджреА рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдкрд░реАрдХреНрд╖рдг рдХреЗ рдмрд╛рдж, рдбреЗрдЯрд╛рдмреЗрд╕ рдФрд░ рдХреА-рд╡реИрд▓реНрдпреВ рд╕реНрдЯреЛрд░ рдХреЗ рд▓рд┐рдП
asyncio
рдбреНрд░рд╛рдЗрд╡рд░реЛрдВ рдХреЗ рдЖрдЧрдорди рдХреЗ рд╕рд╛рде рдЪрд▓ рд░рд╣рд╛ рд╣реИ - рдпрд╣ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╕рдВрднрд╡ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред