Coverage for Lib/asyncio/events.py: 92%

306 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-09 01:31 +0000

1"""Event loop and event loop policy.""" 

2 

3# Contains code from https://github.com/MagicStack/uvloop/tree/v0.16.0 

4# SPDX-License-Identifier: PSF-2.0 AND (MIT OR Apache-2.0) 

5# SPDX-FileCopyrightText: Copyright (c) 2015-2021 MagicStack Inc. http://magic.io 

6 

7__all__ = ( 

8 "AbstractEventLoop", 

9 "AbstractServer", 

10 "Handle", 

11 "TimerHandle", 

12 "get_event_loop", 

13 "set_event_loop", 

14 "new_event_loop", 

15 "_set_running_loop", 

16 "get_running_loop", 

17 "_get_running_loop", 

18) 

19 

20import contextvars 

21import os 

22import signal 

23import socket 

24import subprocess 

25import sys 

26import threading 

27 

28from . import format_helpers 

29 

30 

31class Handle: 

32 """Object returned by callback registration methods.""" 

33 

34 __slots__ = ('_callback', '_args', '_cancelled', '_loop', 

35 '_source_traceback', '_repr', '__weakref__', 

36 '_context') 

37 

38 def __init__(self, callback, args, loop, context=None): 

39 if context is None: 

40 context = contextvars.copy_context() 

41 self._context = context 

42 self._loop = loop 

43 self._callback = callback 

44 self._args = args 

45 self._cancelled = False 

46 self._repr = None 

47 if self._loop.get_debug(): 

48 self._source_traceback = format_helpers.extract_stack( 

49 sys._getframe(1)) 

50 else: 

51 self._source_traceback = None 

52 

53 def _repr_info(self): 

54 info = [self.__class__.__name__] 

55 if self._cancelled: 

56 info.append('cancelled') 

57 if self._callback is not None: 

58 info.append(format_helpers._format_callback_source( 

59 self._callback, self._args, 

60 debug=self._loop.get_debug())) 

61 if self._source_traceback: 

62 frame = self._source_traceback[-1] 

63 info.append(f'created at {frame[0]}:{frame[1]}') 

64 return info 

65 

66 def __repr__(self): 

67 if self._repr is not None: 

68 return self._repr 

69 info = self._repr_info() 

70 return '<{}>'.format(' '.join(info)) 

71 

72 def get_context(self): 

73 return self._context 

74 

75 def cancel(self): 

76 if not self._cancelled: 

77 self._cancelled = True 

78 if self._loop.get_debug(): 

79 # Keep a representation in debug mode to keep callback and 

80 # parameters. For example, to log the warning 

81 # "Executing <Handle...> took 2.5 second" 

82 self._repr = repr(self) 

83 self._callback = None 

84 self._args = None 

85 

86 def cancelled(self): 

87 return self._cancelled 

88 

89 def _run(self): 

90 try: 

91 self._context.run(self._callback, *self._args) 

92 except (SystemExit, KeyboardInterrupt): 

93 raise 

94 except BaseException as exc: 

95 cb = format_helpers._format_callback_source( 

96 self._callback, self._args, 

97 debug=self._loop.get_debug()) 

98 msg = f'Exception in callback {cb}' 

99 context = { 

100 'message': msg, 

101 'exception': exc, 

102 'handle': self, 

103 } 

104 if self._source_traceback: 

105 context['source_traceback'] = self._source_traceback 

106 self._loop.call_exception_handler(context) 

107 self = None # Needed to break cycles when an exception occurs. 

108 

109# _ThreadSafeHandle is used for callbacks scheduled with call_soon_threadsafe 

110# and is thread safe unlike Handle which is not thread safe. 

111class _ThreadSafeHandle(Handle): 

112 

113 __slots__ = ('_lock',) 

114 

115 def __init__(self, callback, args, loop, context=None): 

116 super().__init__(callback, args, loop, context) 

117 self._lock = threading.RLock() 

118 

119 def cancel(self): 

120 with self._lock: 

121 return super().cancel() 

122 

123 def cancelled(self): 

124 with self._lock: 

125 return super().cancelled() 

126 

127 def _run(self): 

128 # The event loop checks for cancellation without holding the lock 

129 # It is possible that the handle is cancelled after the check 

130 # but before the callback is called so check it again after acquiring 

131 # the lock and return without calling the callback if it is cancelled. 

132 with self._lock: 

133 if self._cancelled: 133 ↛ 134line 133 didn't jump to line 134 because the condition on line 133 was never true

134 return 

135 return super()._run() 

136 

137 

138class TimerHandle(Handle): 

139 """Object returned by timed callback registration methods.""" 

140 

141 __slots__ = ['_scheduled', '_when'] 

142 

143 def __init__(self, when, callback, args, loop, context=None): 

144 super().__init__(callback, args, loop, context) 

145 if self._source_traceback: 

146 del self._source_traceback[-1] 

147 self._when = when 

148 self._scheduled = False 

149 

150 def _repr_info(self): 

151 info = super()._repr_info() 

152 pos = 2 if self._cancelled else 1 

153 info.insert(pos, f'when={self._when}') 

154 return info 

155 

156 def __hash__(self): 

157 return hash(self._when) 

158 

159 def __lt__(self, other): 

160 if isinstance(other, TimerHandle): 

161 return self._when < other._when 

162 return NotImplemented 

163 

164 def __le__(self, other): 

165 if isinstance(other, TimerHandle): 

166 return self._when < other._when or self.__eq__(other) 

167 return NotImplemented 

168 

169 def __gt__(self, other): 

170 if isinstance(other, TimerHandle): 

171 return self._when > other._when 

172 return NotImplemented 

173 

174 def __ge__(self, other): 

175 if isinstance(other, TimerHandle): 

176 return self._when > other._when or self.__eq__(other) 

177 return NotImplemented 

178 

179 def __eq__(self, other): 

180 if isinstance(other, TimerHandle): 

181 return (self._when == other._when and 

182 self._callback == other._callback and 

183 self._args == other._args and 

184 self._cancelled == other._cancelled) 

185 return NotImplemented 

186 

187 def cancel(self): 

188 if not self._cancelled: 188 ↛ 190line 188 didn't jump to line 190 because the condition on line 188 was always true

189 self._loop._timer_handle_cancelled(self) 

190 super().cancel() 

191 

192 def when(self): 

193 """Return a scheduled callback time. 

194 

195 The time is an absolute timestamp, using the same time 

196 reference as loop.time(). 

197 """ 

198 return self._when 

199 

200 

201class AbstractServer: 

202 """Abstract server returned by create_server().""" 

203 

204 def close(self): 

205 """Stop serving. This leaves existing connections open.""" 

206 raise NotImplementedError 

207 

208 def close_clients(self): 

209 """Close all active connections.""" 

210 raise NotImplementedError 

211 

212 def abort_clients(self): 

213 """Close all active connections immediately.""" 

214 raise NotImplementedError 

215 

216 def get_loop(self): 

217 """Get the event loop the Server object is attached to.""" 

218 raise NotImplementedError 

219 

220 def is_serving(self): 

221 """Return True if the server is accepting connections.""" 

222 raise NotImplementedError 

223 

224 async def start_serving(self): 

225 """Start accepting connections. 

226 

227 This method is idempotent, so it can be called when 

228 the server is already being serving. 

229 """ 

230 raise NotImplementedError 

231 

232 async def serve_forever(self): 

233 """Start accepting connections until the coroutine is cancelled. 

234 

235 The server is closed when the coroutine is cancelled. 

236 """ 

237 raise NotImplementedError 

238 

239 async def wait_closed(self): 

240 """Coroutine to wait until service is closed.""" 

241 raise NotImplementedError 

242 

243 async def __aenter__(self): 

244 return self 

245 

246 async def __aexit__(self, *exc): 

247 self.close() 

248 await self.wait_closed() 

249 

250 

251class AbstractEventLoop: 

252 """Abstract event loop.""" 

253 

254 # Running and stopping the event loop. 

255 

256 def run_forever(self): 

257 """Run the event loop until stop() is called.""" 

258 raise NotImplementedError 

259 

260 def run_until_complete(self, future): 

261 """Run the event loop until a Future is done. 

262 

263 Return the Future's result, or raise its exception. 

264 """ 

265 raise NotImplementedError 

266 

267 def stop(self): 

268 """Stop the event loop as soon as reasonable. 

269 

270 Exactly how soon that is may depend on the implementation, but 

271 no more I/O callbacks should be scheduled. 

272 """ 

273 raise NotImplementedError 

274 

275 def is_running(self): 

276 """Return whether the event loop is currently running.""" 

277 raise NotImplementedError 

278 

279 def is_closed(self): 

280 """Returns True if the event loop was closed.""" 

281 raise NotImplementedError 

282 

283 def close(self): 

284 """Close the loop. 

285 

286 The loop should not be running. 

287 

288 This is idempotent and irreversible. 

289 

290 No other methods should be called after this one. 

291 """ 

292 raise NotImplementedError 

293 

294 async def shutdown_asyncgens(self): 

295 """Shutdown all active asynchronous generators.""" 

296 raise NotImplementedError 

297 

298 async def shutdown_default_executor(self): 

299 """Schedule the shutdown of the default executor.""" 

300 raise NotImplementedError 

301 

302 # Methods scheduling callbacks. All these return Handles. 

303 

304 def _timer_handle_cancelled(self, handle): 

305 """Notification that a TimerHandle has been cancelled.""" 

306 raise NotImplementedError 

307 

308 def call_soon(self, callback, *args, context=None): 

309 return self.call_later(0, callback, *args, context=context) 

310 

311 def call_later(self, delay, callback, *args, context=None): 

312 raise NotImplementedError 

313 

314 def call_at(self, when, callback, *args, context=None): 

315 raise NotImplementedError 

316 

317 def time(self): 

318 raise NotImplementedError 

319 

320 def create_future(self): 

321 raise NotImplementedError 

322 

323 # Method scheduling a coroutine object: create a task. 

324 

325 def create_task(self, coro, **kwargs): 

326 raise NotImplementedError 

327 

328 # Methods for interacting with threads. 

329 

330 def call_soon_threadsafe(self, callback, *args, context=None): 

331 raise NotImplementedError 

332 

333 def run_in_executor(self, executor, func, *args): 

334 raise NotImplementedError 

335 

336 def set_default_executor(self, executor): 

337 raise NotImplementedError 

338 

339 # Network I/O methods returning Futures. 

340 

341 async def getaddrinfo(self, host, port, *, 

342 family=0, type=0, proto=0, flags=0): 

343 raise NotImplementedError 

344 

345 async def getnameinfo(self, sockaddr, flags=0): 

346 raise NotImplementedError 

347 

348 async def create_connection( 

349 self, protocol_factory, host=None, port=None, 

350 *, ssl=None, family=0, proto=0, 

351 flags=0, sock=None, local_addr=None, 

352 server_hostname=None, 

353 ssl_handshake_timeout=None, 

354 ssl_shutdown_timeout=None, 

355 happy_eyeballs_delay=None, interleave=None): 

356 raise NotImplementedError 

357 

358 async def create_server( 

359 self, protocol_factory, host=None, port=None, 

360 *, family=socket.AF_UNSPEC, 

361 flags=socket.AI_PASSIVE, sock=None, backlog=100, 

362 ssl=None, reuse_address=None, reuse_port=None, 

363 keep_alive=None, 

364 ssl_handshake_timeout=None, 

365 ssl_shutdown_timeout=None, 

366 start_serving=True): 

367 """A coroutine which creates a TCP server bound to host and port. 

368 

369 The return value is a Server object which can be used to stop 

370 the service. 

371 

372 If host is an empty string or None all interfaces are assumed 

373 and a list of multiple sockets will be returned (most likely 

374 one for IPv4 and another one for IPv6). The host parameter can also 

375 be a sequence (e.g. list) of hosts to bind to. 

376 

377 family can be set to either AF_INET or AF_INET6 to force the 

378 socket to use IPv4 or IPv6. If not set it will be determined 

379 from host (defaults to AF_UNSPEC). 

380 

381 flags is a bitmask for getaddrinfo(). 

382 

383 sock can optionally be specified in order to use a preexisting 

384 socket object. 

385 

386 backlog is the maximum number of queued connections passed to 

387 listen() (defaults to 100). 

388 

389 ssl can be set to an SSLContext to enable SSL over the 

390 accepted connections. 

391 

392 reuse_address tells the kernel to reuse a local socket in 

393 TIME_WAIT state, without waiting for its natural timeout to 

394 expire. If not specified will automatically be set to True on 

395 UNIX. 

396 

397 reuse_port tells the kernel to allow this endpoint to be bound to 

398 the same port as other existing endpoints are bound to, so long as 

399 they all set this flag when being created. This option is not 

400 supported on Windows. 

401 

402 keep_alive set to True keeps connections active by enabling the 

403 periodic transmission of messages. 

404 

405 ssl_handshake_timeout is the time in seconds that an SSL server 

406 will wait for completion of the SSL handshake before aborting the 

407 connection. Default is 60s. 

408 

409 ssl_shutdown_timeout is the time in seconds that an SSL server 

410 will wait for completion of the SSL shutdown procedure 

411 before aborting the connection. Default is 30s. 

412 

413 start_serving set to True (default) causes the created server 

414 to start accepting connections immediately. When set to False, 

415 the user should await Server.start_serving() or 

416 Server.serve_forever() to make the server to start accepting 

417 connections. 

418 """ 

419 raise NotImplementedError 

420 

421 async def sendfile(self, transport, file, offset=0, count=None, 

422 *, fallback=True): 

423 """Send a file through a transport. 

424 

425 Return an amount of sent bytes. 

426 """ 

427 raise NotImplementedError 

428 

429 async def start_tls(self, transport, protocol, sslcontext, *, 

430 server_side=False, 

431 server_hostname=None, 

432 ssl_handshake_timeout=None, 

433 ssl_shutdown_timeout=None): 

434 """Upgrade a transport to TLS. 

435 

436 Return a new transport that *protocol* should start using 

437 immediately. 

438 """ 

439 raise NotImplementedError 

440 

441 async def create_unix_connection( 

442 self, protocol_factory, path=None, *, 

443 ssl=None, sock=None, 

444 server_hostname=None, 

445 ssl_handshake_timeout=None, 

446 ssl_shutdown_timeout=None): 

447 raise NotImplementedError 

448 

449 async def create_unix_server( 

450 self, protocol_factory, path=None, *, 

451 sock=None, backlog=100, ssl=None, 

452 ssl_handshake_timeout=None, 

453 ssl_shutdown_timeout=None, 

454 start_serving=True, mode=None): 

455 """A coroutine which creates a UNIX Domain Socket server. 

456 

457 The return value is a Server object, which can be used to stop 

458 the service. 

459 

460 path is a str, representing a file system path to bind the 

461 server socket to. 

462 

463 sock can optionally be specified in order to use a preexisting 

464 socket object. 

465 

466 backlog is the maximum number of queued connections passed to 

467 listen() (defaults to 100). 

468 

469 ssl can be set to an SSLContext to enable SSL over the 

470 accepted connections. 

471 

472 ssl_handshake_timeout is the time in seconds that an SSL server 

473 will wait for the SSL handshake to complete (defaults to 60s). 

474 

475 ssl_shutdown_timeout is the time in seconds that an SSL server 

476 will wait for the SSL shutdown to finish (defaults to 30s). 

477 

478 start_serving set to True (default) causes the created server 

479 to start accepting connections immediately. When set to False, 

480 the user should await Server.start_serving() or 

481 Server.serve_forever() to make the server to start accepting 

482 connections. 

483 

484 mode, if not None, is applied to the socket file created for 

485 path with os.chmod() after binding and before the server 

486 starts accepting connections. 

487 """ 

488 raise NotImplementedError 

489 

490 async def connect_accepted_socket( 

491 self, protocol_factory, sock, 

492 *, ssl=None, 

493 ssl_handshake_timeout=None, 

494 ssl_shutdown_timeout=None): 

495 """Handle an accepted connection. 

496 

497 This is used by servers that accept connections outside of 

498 asyncio, but use asyncio to handle connections. 

499 

500 This method is a coroutine. When completed, the coroutine 

501 returns a (transport, protocol) pair. 

502 """ 

503 raise NotImplementedError 

504 

505 async def create_datagram_endpoint(self, protocol_factory, 

506 local_addr=None, remote_addr=None, *, 

507 family=0, proto=0, flags=0, 

508 reuse_address=None, reuse_port=None, 

509 allow_broadcast=None, sock=None): 

510 """A coroutine which creates a datagram endpoint. 

511 

512 This method will try to establish the endpoint in the background. 

513 When successful, the coroutine returns a (transport, protocol) pair. 

514 

515 protocol_factory must be a callable returning a protocol instance. 

516 

517 socket family AF_INET, socket.AF_INET6 or socket.AF_UNIX depending 

518 on host (or family if specified), socket type SOCK_DGRAM. 

519 

520 reuse_address tells the kernel to reuse a local socket in 

521 TIME_WAIT state, without waiting for its natural timeout to 

522 expire. If not specified it will automatically be set to True on 

523 UNIX. 

524 

525 reuse_port tells the kernel to allow this endpoint to be bound to 

526 the same port as other existing endpoints are bound to, so long as 

527 they all set this flag when being created. This option is not 

528 supported on Windows and some UNIX's. If the 

529 :py:data:`~socket.SO_REUSEPORT` constant is not defined then this 

530 capability is unsupported. 

531 

532 allow_broadcast tells the kernel to allow this endpoint to send 

533 messages to the broadcast address. 

534 

535 sock can optionally be specified in order to use a preexisting 

536 socket object. 

537 """ 

538 raise NotImplementedError 

539 

540 # Pipes and subprocesses. 

541 

542 async def connect_read_pipe(self, protocol_factory, pipe): 

543 """Register read pipe in event loop. Set the pipe to non-blocking mode. 

544 

545 protocol_factory should instantiate object with Protocol interface. 

546 pipe is a file-like object. 

547 Return pair (transport, protocol), where transport supports the 

548 ReadTransport interface.""" 

549 # The reason to accept file-like object instead of just file descriptor 

550 # is: we need to own pipe and close it at transport finishing 

551 # Can got complicated errors if pass f.fileno(), 

552 # close fd in pipe transport then close f and vice versa. 

553 raise NotImplementedError 

554 

555 async def connect_write_pipe(self, protocol_factory, pipe): 

556 """Register write pipe in event loop. 

557 

558 protocol_factory should instantiate object with BaseProtocol 

559 interface. 

560 Pipe is file-like object already switched to nonblocking. 

561 Return pair (transport, protocol), where transport support 

562 WriteTransport interface.""" 

563 # The reason to accept file-like object instead of just file descriptor 

564 # is: we need to own pipe and close it at transport finishing 

565 # Can got complicated errors if pass f.fileno(), 

566 # close fd in pipe transport then close f and vice versa. 

567 raise NotImplementedError 

568 

569 async def subprocess_shell(self, protocol_factory, cmd, *, 

570 stdin=subprocess.PIPE, 

571 stdout=subprocess.PIPE, 

572 stderr=subprocess.PIPE, 

573 **kwargs): 

574 raise NotImplementedError 

575 

576 async def subprocess_exec(self, protocol_factory, *args, 

577 stdin=subprocess.PIPE, 

578 stdout=subprocess.PIPE, 

579 stderr=subprocess.PIPE, 

580 **kwargs): 

581 raise NotImplementedError 

582 

583 # Ready-based callback registration methods. 

584 # The add_*() methods return None. 

585 # The remove_*() methods return True if something was removed, 

586 # False if there was nothing to delete. 

587 

588 def add_reader(self, fd, callback, *args): 

589 raise NotImplementedError 

590 

591 def remove_reader(self, fd): 

592 raise NotImplementedError 

593 

594 def add_writer(self, fd, callback, *args): 

595 raise NotImplementedError 

596 

597 def remove_writer(self, fd): 

598 raise NotImplementedError 

599 

600 # Completion based I/O methods returning Futures. 

601 

602 async def sock_recv(self, sock, nbytes): 

603 raise NotImplementedError 

604 

605 async def sock_recv_into(self, sock, buf): 

606 raise NotImplementedError 

607 

608 async def sock_recvfrom(self, sock, bufsize): 

609 raise NotImplementedError 

610 

611 async def sock_recvfrom_into(self, sock, buf, nbytes=0): 

612 raise NotImplementedError 

613 

614 async def sock_sendall(self, sock, data): 

615 raise NotImplementedError 

616 

617 async def sock_sendto(self, sock, data, address): 

618 raise NotImplementedError 

619 

620 async def sock_connect(self, sock, address): 

621 raise NotImplementedError 

622 

623 async def sock_accept(self, sock): 

624 raise NotImplementedError 

625 

626 async def sock_sendfile(self, sock, file, offset=0, count=None, 

627 *, fallback=None): 

628 raise NotImplementedError 

629 

630 # Signal handling. 

631 

632 def add_signal_handler(self, sig, callback, *args): 

633 raise NotImplementedError 

634 

635 def remove_signal_handler(self, sig): 

636 raise NotImplementedError 

637 

638 # Task factory. 

639 

640 def set_task_factory(self, factory): 

641 raise NotImplementedError 

642 

643 def get_task_factory(self): 

644 raise NotImplementedError 

645 

646 # Error handlers. 

647 

648 def get_exception_handler(self): 

649 raise NotImplementedError 

650 

651 def set_exception_handler(self, handler): 

652 raise NotImplementedError 

653 

654 def default_exception_handler(self, context): 

655 raise NotImplementedError 

656 

657 def call_exception_handler(self, context): 

658 raise NotImplementedError 

659 

660 # Debug flag management. 

661 

662 def get_debug(self): 

663 raise NotImplementedError 

664 

665 def set_debug(self, enabled): 

666 raise NotImplementedError 

667 

668 

669class _Local(threading.local): 

670 _loop = None 

671 

672 

673_local = _Local() 

674 

675 

676# A TLS for the running event loop, used by _get_running_loop. 

677class _RunningLoop(threading.local): 

678 loop_pid = (None, None) 

679 

680 

681_running_loop = _RunningLoop() 

682 

683 

684def get_running_loop(): 

685 """Return the running event loop. Raise a RuntimeError if there is none. 

686 

687 This function is thread-specific. 

688 """ 

689 # NOTE: this function is implemented in C (see _asynciomodule.c) 

690 loop = _get_running_loop() 

691 if loop is None: 

692 raise RuntimeError('no running event loop') 

693 return loop 

694 

695 

696def _get_running_loop(): 

697 """Return the running event loop or None. 

698 

699 This is a low-level function intended to be used by event loops. 

700 This function is thread-specific. 

701 """ 

702 # NOTE: this function is implemented in C (see _asynciomodule.c) 

703 running_loop, pid = _running_loop.loop_pid 

704 if running_loop is not None and pid == os.getpid(): 

705 return running_loop 

706 

707 

708def _set_running_loop(loop): 

709 """Set the running event loop. 

710 

711 This is a low-level function intended to be used by event loops. 

712 This function is thread-specific. 

713 """ 

714 # NOTE: this function is implemented in C (see _asynciomodule.c) 

715 _running_loop.loop_pid = (loop, os.getpid()) 

716 

717 

718def _get_event_loop(): 

719 """Return the event loop set for the current thread. 

720 

721 Raise a RuntimeError if no event loop has been set for the current 

722 thread. This is the slow path of get_event_loop(); the running loop 

723 is checked by the caller. 

724 """ 

725 loop = _local._loop 

726 if loop is None: 

727 raise RuntimeError('There is no current event loop in thread %r.' 

728 % threading.current_thread().name) 

729 return loop 

730 

731 

732def get_event_loop(): 

733 """Return an asyncio event loop. 

734 

735 When called from a coroutine or a callback (e.g. scheduled with call_soon 

736 or similar API), this function will always return the running event loop. 

737 

738 If there is no running event loop set, the function will return 

739 the loop set by ``set_event_loop()``, or raise a RuntimeError if 

740 no loop has been set. 

741 """ 

742 # NOTE: this function is implemented in C (see _asynciomodule.c) 

743 current_loop = _get_running_loop() 

744 if current_loop is not None: 

745 return current_loop 

746 return _get_event_loop() 

747 

748 

749def set_event_loop(loop): 

750 """Set the event loop for the current thread to loop. 

751 

752 If loop is None, the current event loop is unset. 

753 """ 

754 if loop is not None and not isinstance(loop, AbstractEventLoop): 

755 raise TypeError(f"loop must be an instance of AbstractEventLoop or None, not '{type(loop).__name__}'") 

756 _local._loop = loop 

757 

758 

759def new_event_loop(): 

760 """Create and return a new event loop object.""" 

761 if sys.platform == 'win32': 761 ↛ 762line 761 didn't jump to line 762 because the condition on line 761 was never true

762 from .windows_events import EventLoop 

763 else: 

764 from .unix_events import EventLoop 

765 return EventLoop() 

766 

767 

768# Alias pure-Python implementations for testing purposes. 

769_py__get_running_loop = _get_running_loop 

770_py__set_running_loop = _set_running_loop 

771_py_get_running_loop = get_running_loop 

772_py_get_event_loop = get_event_loop 

773 

774 

775try: 

776 # get_event_loop() is one of the most frequently called 

777 # functions in asyncio. Pure Python implementation is 

778 # about 4 times slower than C-accelerated. 

779 from _asyncio import (_get_running_loop, _set_running_loop, 

780 get_running_loop, get_event_loop) 

781except ImportError: 

782 pass 

783else: 

784 # Alias C implementations for testing purposes. 

785 _c__get_running_loop = _get_running_loop 

786 _c__set_running_loop = _set_running_loop 

787 _c_get_running_loop = get_running_loop 

788 _c_get_event_loop = get_event_loop 

789 

790 

791if hasattr(os, 'fork'): 791 ↛ exitline 791 didn't exit the module because the condition on line 791 was always true

792 def on_fork(): 

793 # Reset the loop and wakeupfd in the forked child process. 

794 global _local 

795 _local = _Local() 

796 _set_running_loop(None) 

797 signal.set_wakeup_fd(-1) 

798 

799 os.register_at_fork(after_in_child=on_fork)