Vòng lặp sự kiện¶
Source code: Lib/asyncio/events.py, Lib/asyncio/base_events.py
Lời nói đầu
Vòng lặp sự kiện là cốt lõi của mọi ứng dụng asyncio. Vòng lặp sự kiện chạy các tác vụ và lệnh gọi lại không đồng bộ, thực hiện các hoạt động IO mạng và chạy các quy trình con.
Các nhà phát triển ứng dụng thường nên sử dụng các hàm asyncio cấp cao, chẳng hạn như asyncio.run() và hiếm khi cần tham chiếu đối tượng vòng lặp hoặc gọi các phương thức của nó. Phần này chủ yếu dành cho các tác giả viết mã, thư viện và khung công tác cấp thấp hơn, những người cần kiểm soát tốt hơn hành vi của vòng lặp sự kiện.
Lấy vòng lặp sự kiện
Các hàm cấp thấp sau đây có thể được sử dụng để lấy, đặt hoặc tạo vòng lặp sự kiện:
- asyncio.get_running_loop()¶
Trả về vòng lặp sự kiện đang chạy trong chuỗi hệ điều hành hiện tại.
Tăng
RuntimeErrornếu không có vòng lặp sự kiện đang chạy.Hàm này chỉ có thể được gọi từ một coroutine hoặc một lệnh gọi lại.
Added in version 3.7.
- asyncio.get_event_loop()¶
Nhận vòng lặp sự kiện hiện tại.
Khi được gọi từ một coroutine hoặc một lệnh gọi lại (ví dụ: được lên lịch bằng call_soon hoặc API tương tự), hàm này sẽ luôn trả về vòng lặp sự kiện đang chạy.
Nếu không có bộ vòng lặp sự kiện đang chạy, hàm sẽ trả về kết quả của lệnh gọi
get_event_loop_policy().get_event_loop().Vì hàm này có hành vi khá phức tạp (đặc biệt là khi sử dụng chính sách vòng lặp sự kiện tùy chỉnh), nên việc sử dụng hàm
get_running_loop()được ưu tiên hơnget_event_loop()trong coroutine và lệnh gọi lại.Như đã lưu ý ở trên, hãy cân nhắc sử dụng hàm
asyncio.run()cấp cao hơn, thay vì sử dụng các hàm cấp thấp hơn này để tạo và đóng vòng lặp sự kiện theo cách thủ công.Thay đổi trong phiên bản 3.14: Tăng
RuntimeErrornếu không có vòng lặp sự kiện hiện tại.Ghi chú
Hệ thống chính sách
asynciokhông được dùng nữa và sẽ bị xóa trong Python 3.16; từ đó trở đi, hàm này sẽ trả về vòng lặp sự kiện đang chạy hiện tại nếu có, nếu không nó sẽ trả về vòng lặp doset_event_loop()thiết lập.
- asyncio.set_event_loop(loop)¶
Đặt loop làm vòng lặp sự kiện hiện tại cho chuỗi hệ điều hành hiện tại.
- asyncio.new_event_loop()¶
Tạo và trả về một đối tượng vòng lặp sự kiện mới.
Lưu ý rằng hoạt động của các hàm get_event_loop(), set_event_loop() và new_event_loop() có thể được thay đổi bởi setting a custom event loop policy.
Nội dung
Trang tài liệu này chứa các phần sau:
Phần Event Loop Methods là tài liệu tham khảo về API vòng lặp sự kiện;
Phần Callback Handles ghi lại các phiên bản
HandlevàTimerHandleđược trả về từ các phương pháp lập lịch nhưloop.call_soon()vàloop.call_later();Các loại tài liệu của phần Server Objects được trả về từ các phương thức vòng lặp sự kiện như
loop.create_server();Phần Event Loop Implementations ghi lại các lớp
SelectorEventLoopvàProactorEventLoop;Phần Examples giới thiệu cách làm việc với một số API vòng lặp sự kiện.
Phương pháp vòng lặp sự kiện¶
Vòng lặp sự kiện có API low-level cho các mục sau:
Chạy và dừng vòng lặp¶
- loop.run_until_complete(future)¶
Chạy cho đến khi future (một phiên bản của
Future) hoàn tất.Nếu đối số là coroutine object thì nó được lên lịch ngầm để chạy dưới dạng
asyncio.Task.Trả về kết quả của Tương lai hoặc đưa ra ngoại lệ của nó.
- loop.run_forever()¶
Chạy vòng lặp sự kiện cho đến khi
stop()được gọi.Nếu
stop()được gọi trước khirun_forever()được gọi, vòng lặp sẽ thăm dò bộ chọn I/O một lần với thời gian chờ bằng 0, chạy tất cả lệnh gọi lại đã lên lịch để phản hồi các sự kiện I/O (và những sự kiện đã được lên lịch), rồi thoát.Nếu
stop()được gọi trong khirun_forever()đang chạy, vòng lặp sẽ chạy loạt lệnh gọi lại hiện tại rồi thoát ra. Lưu ý rằng lệnh gọi lại mới được lên lịch bởi lệnh gọi lại sẽ không chạy trong trường hợp này; thay vào đó, chúng sẽ chạy vào lần tiếp theorun_forever()hoặcrun_until_complete()được gọi.
- loop.stop()¶
Dừng vòng lặp sự kiện.
- loop.is_running()¶
Trả về
Truenếu vòng lặp sự kiện hiện đang chạy.
- loop.is_closed()¶
Trả về
Truenếu vòng lặp sự kiện đã bị đóng.
- loop.close()¶
Đóng vòng lặp sự kiện.
Vòng lặp không được chạy khi hàm này được gọi. Mọi lệnh gọi lại đang chờ xử lý sẽ bị loại bỏ.
Phương thức này xóa tất cả các hàng đợi và tắt bộ thực thi, nhưng không đợi người thực thi kết thúc.
Phương pháp này là bình thường và không thể đảo ngược. Không có phương thức nào khác được gọi sau khi vòng lặp sự kiện được đóng lại.
- async loop.shutdown_asyncgens()¶
Lên lịch đóng tất cả các đối tượng asynchronous generator hiện đang mở bằng lệnh gọi
aclose(). Sau khi gọi phương thức này, vòng lặp sự kiện sẽ đưa ra cảnh báo nếu một trình tạo không đồng bộ mới được lặp lại. Điều này nên được sử dụng để hoàn thiện một cách đáng tin cậy tất cả các trình tạo không đồng bộ theo lịch trình.Lưu ý rằng không cần gọi hàm này khi sử dụng
asyncio.run().Ví dụ:
thử: loop.run_forever() cuối cùng: loop.run_until_complete(loop.shutdown_asyncgens()) loop.close()
Added in version 3.6.
- async loop.shutdown_default_executor(timeout=None)¶
Lên lịch đóng trình thực thi mặc định và đợi nó tham gia tất cả các luồng trong
ThreadPoolExecutor. Khi phương thức này đã được gọi, việc sử dụng trình thực thi mặc định vớiloop.run_in_executor()sẽ tạo raRuntimeError.Tham số timeout chỉ định lượng thời gian (tính bằng
floatgiây) mà người thực thi sẽ được cung cấp để hoàn tất việc tham gia. Với mặc định,None, người thực thi được phép có thời gian không giới hạn.Nếu đạt đến timeout,
RuntimeWarningsẽ được phát ra và trình thực thi mặc định sẽ bị chấm dứt mà không cần đợi các luồng của nó kết thúc việc nối.Ghi chú
Không gọi phương thức này khi sử dụng
asyncio.run(), vìasyncio.run()sẽ tự động xử lý việc tắt trình thực thi mặc định.Added in version 3.9.
Thay đổi trong phiên bản 3.12: Đã thêm tham số timeout.
Lên lịch gọi lại¶
- loop.call_soon(callback, *args, context=None)¶
Lên lịch gọi callback callback với các đối số args ở lần lặp tiếp theo của vòng lặp sự kiện.
Trả về một phiên bản của
asyncio.Handle, phiên bản này sau này có thể được sử dụng để hủy lệnh gọi lại.Cuộc gọi lại được gọi theo thứ tự chúng được đăng ký. Mỗi cuộc gọi lại sẽ được gọi chính xác một lần.
Đối số context chỉ có từ khóa tùy chọn chỉ định một
contextvars.Contexttùy chỉnh để callback chạy vào. Lệnh gọi lại sử dụng ngữ cảnh hiện tại khi không cung cấp context.Không giống như
call_soon_threadsafe(), phương pháp này không an toàn cho luồng.
- loop.call_soon_threadsafe(callback, *args, context=None)¶
Một biến thể an toàn theo luồng của
call_soon(). Khi lên lịch gọi lại từ một luồng khác, hàm must này sẽ được sử dụng vìcall_soon()không an toàn cho luồng.Hàm này an toàn khi được gọi từ ngữ cảnh gửi lại hoặc trình xử lý tín hiệu, tuy nhiên, sẽ không an toàn hoặc hiệu quả khi sử dụng thẻ điều khiển được trả về trong các ngữ cảnh như vậy.
Tăng
RuntimeErrornếu được gọi trên một vòng lặp đã bị đóng. Điều này có thể xảy ra trên luồng phụ khi ứng dụng chính đang tắt.Xem phần concurrency and multithreading của tài liệu.
Thay đổi trong phiên bản 3.7: Tham số chỉ từ khóa context đã được thêm vào. Xem PEP 567 để biết thêm chi tiết.
Ghi chú
Hầu hết các chức năng lập lịch asyncio không cho phép truyền đối số từ khóa. Để làm điều đó, hãy sử dụng functools.partial():
lịch trình # will "in ("Xin chào", tuôn ra = Đúng)"
loop.call_soon(
functools.partial(in, "Xin chào", tuôn ra=True))
Sử dụng các đối tượng một phần thường thuận tiện hơn so với sử dụng lambdas, vì asyncio có thể hiển thị các đối tượng một phần tốt hơn trong các thông báo gỡ lỗi và lỗi.
Lên lịch gọi lại bị trì hoãn¶
Vòng lặp sự kiện cung cấp cơ chế lên lịch cho các hàm gọi lại sẽ được gọi vào một thời điểm nào đó trong tương lai. Vòng lặp sự kiện sử dụng đồng hồ đơn điệu để theo dõi thời gian.
- loop.call_later(delay, callback, *args, context=None)¶
Lên lịch gọi callback sau số giây delay đã cho (có thể là int hoặc float).
Một phiên bản
asyncio.TimerHandleđược trả về có thể được sử dụng để hủy cuộc gọi lại.callback sẽ được gọi đúng một lần. Nếu hai lệnh gọi lại được lên lịch vào cùng một thời điểm thì thứ tự chúng được gọi sẽ không được xác định.
args vị trí tùy chọn sẽ được chuyển đến lệnh gọi lại khi nó được gọi. Sử dụng
functools.partial()to pass keyword arguments đến callback.Đối số context chỉ có từ khóa tùy chọn cho phép chỉ định một
contextvars.Contexttùy chỉnh để callback chạy vào. Ngữ cảnh hiện tại được sử dụng khi không cung cấp context.Ghi chú
Để đảm bảo hiệu suất, các lệnh gọi lại được lên lịch bằng
loop.call_later()có thể chạy sớm tới một độ phân giải đồng hồ (xemtime.get_clock_info('monotonic').resolution).Thay đổi trong phiên bản 3.7: Tham số chỉ từ khóa context đã được thêm vào. Xem PEP 567 để biết thêm chi tiết.
Thay đổi trong phiên bản 3.8: Trong Python 3.7 trở về trước với cách triển khai vòng lặp sự kiện mặc định, delay không thể vượt quá một ngày. Điều này đã được sửa trong Python 3.8.
- loop.call_at(when, callback, *args, context=None)¶
Lên lịch gọi callback tại dấu thời gian tuyệt đối nhất định when (int hoặc float), sử dụng cùng tham chiếu thời gian như
loop.time().Hành vi của phương pháp này giống như
call_later().Một phiên bản
asyncio.TimerHandleđược trả về có thể được sử dụng để hủy cuộc gọi lại.Ghi chú
Để đảm bảo hiệu suất, các lệnh gọi lại được lên lịch bằng
loop.call_at()có thể chạy sớm tới một độ phân giải đồng hồ (xemtime.get_clock_info('monotonic').resolution).Thay đổi trong phiên bản 3.7: Tham số chỉ từ khóa context đã được thêm vào. Xem PEP 567 để biết thêm chi tiết.
Thay đổi trong phiên bản 3.8: Trong Python 3.7 trở về trước với cách triển khai vòng lặp sự kiện mặc định, sự khác biệt giữa when và thời gian hiện tại không được vượt quá một ngày. Điều này đã được sửa trong Python 3.8.
- loop.time()¶
Trả về thời gian hiện tại, dưới dạng giá trị
float, theo đồng hồ đơn điệu bên trong của vòng lặp sự kiện.
Ghi chú
Thay đổi trong phiên bản 3.8: Trong Python 3.7 trở về trước, thời gian chờ (delay tương đối hoặc when tuyệt đối) không được vượt quá một ngày. Điều này đã được sửa trong Python 3.8.
Xem thêm
Chức năng asyncio.sleep().
Tạo ra tương lai và nhiệm vụ¶
- loop.create_future()¶
Tạo một đối tượng
asyncio.Futuregắn vào vòng lặp sự kiện.Đây là cách ưa thích để tạo Hợp đồng tương lai trong asyncio. Điều này cho phép các vòng lặp sự kiện của bên thứ ba cung cấp các cách triển khai thay thế cho đối tượng Tương lai (với hiệu suất hoặc công cụ tốt hơn).
Added in version 3.5.2.
- loop.create_task(coro, *, name=None, context=None, eager_start=None, **kwargs)¶
Lên lịch thực hiện coroutine coro. Trả về một đối tượng
Task.Vòng lặp sự kiện của bên thứ ba có thể sử dụng lớp con
Taskcủa riêng họ để có khả năng tương tác. Trong trường hợp này, loại kết quả là lớp con củaTask.Chữ ký hàm đầy đủ phần lớn giống với chữ ký của hàm tạo
Task(hoặc nhà máy) - tất cả các đối số từ khóa cho hàm này đều được chuyển qua giao diện đó.Nếu đối số name được cung cấp chứ không phải
None, thì đối số đó sẽ được đặt làm tên của tác vụ bằngTask.set_name().Đối số context chỉ có từ khóa tùy chọn cho phép chỉ định một
contextvars.Contexttùy chỉnh để coro chạy vào. Bản sao ngữ cảnh hiện tại được tạo khi không cung cấp context.Đối số eager_start chỉ có từ khóa tùy chọn cho phép chỉ định xem tác vụ sẽ được thực thi một cách háo hức trong khi gọi tới create_task hay được lên lịch sau. Nếu eager_start không được thông qua, chế độ do
loop.set_task_factory()đặt sẽ được sử dụng.Thay đổi trong phiên bản 3.8: Đã thêm tham số name.
Thay đổi trong phiên bản 3.11: Đã thêm tham số context.
Thay đổi trong phiên bản 3.13.3: Đã thêm
kwargsđể chuyển các tham số bổ sung tùy ý, bao gồmnamevàcontext.Thay đổi trong phiên bản 3.13.4: Đã khôi phục thay đổi chuyển sang name và context (nếu là Không), trong khi vẫn chuyển các đối số từ khóa tùy ý khác (để tránh phá vỡ khả năng tương thích ngược với 3.13.3).
Thay đổi trong phiên bản 3.14: Tất cả kwargs hiện đã được chuyển tiếp. Tham số eager_start hoạt động với các nhà máy nhiệm vụ háo hức.
- loop.set_task_factory(factory)¶
Đặt nhà máy tác vụ sẽ được
loop.create_task()sử dụng.Nếu factory là
Nonethì nhà máy tác vụ mặc định sẽ được đặt. Nếu không, factory phải là callable có chữ ký khớp với(loop, coro, **kwargs), trong đó loop là tham chiếu đến vòng lặp sự kiện đang hoạt động và coro là đối tượng coroutine. Đối tượng có thể gọi phải chuyển tất cả kwargs và trả về một đối tượng tương thích vớiasyncio.Task.Thay đổi trong phiên bản 3.13.3: Yêu cầu tất cả kwargs được chuyển cho
asyncio.Task.Thay đổi trong phiên bản 3.13.4: name không còn được chuyển đến các nhà máy nhiệm vụ nữa. context không còn được chuyển đến các nhà máy nhiệm vụ nếu đó là
None.Thay đổi trong phiên bản 3.14: name và context hiện lại được chuyển giao vô điều kiện cho các nhà máy nhiệm vụ.
- loop.get_task_factory()¶
Trả về nhà máy tác vụ hoặc
Nonenếu nhà máy mặc định đang được sử dụng.
Mở kết nối mạng¶
- async loop.create_connection(protocol_factory, host=None, port=None, *, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, happy_eyeballs_delay=None, interleave=None, all_errors=False)¶
Mở kết nối truyền tải trực tuyến đến một địa chỉ nhất định được chỉ định bởi host và port.
Họ socket có thể là
AF_INEThoặcAF_INET6tùy thuộc vào host (hoặc đối số family, nếu được cung cấp).Loại ổ cắm sẽ là
SOCK_STREAM.protocol_factory phải là một phương thức có thể gọi được và trả về việc triển khai asyncio protocol.
Phương pháp này sẽ cố gắng thiết lập kết nối ở chế độ nền. Khi thành công, nó trả về một cặp
(transport, protocol).Bản tóm tắt theo trình tự thời gian của hoạt động cơ bản như sau:
Kết nối được thiết lập và transport được tạo cho nó.
protocol_factory được gọi mà không có đối số và dự kiến sẽ trả về một phiên bản protocol.
Phiên bản giao thức được kết hợp với việc vận chuyển bằng cách gọi phương thức
connection_made()của nó.Một bộ dữ liệu
(transport, protocol)được trả về thành công.
Vận chuyển được tạo là luồng hai chiều phụ thuộc vào việc triển khai.
Các lập luận khác:
ssl: nếu được cung cấp và không sai, quá trình vận chuyển SSL/TLS sẽ được tạo (theo mặc định, quá trình vận chuyển TCP đơn giản sẽ được tạo). Nếu ssl là một đối tượng
ssl.SSLContext, ngữ cảnh này được sử dụng để tạo phương tiện vận chuyển; nếu ssl làTrue, ngữ cảnh mặc định được trả về từssl.create_default_context()sẽ được sử dụng.Xem thêm
server_hostname đặt hoặc ghi đè tên máy chủ mà chứng chỉ của máy chủ mục tiêu sẽ được so khớp. Chỉ nên được thông qua nếu ssl không phải là
None. Theo mặc định, giá trị của đối số host được sử dụng. Nếu host trống thì không có giá trị mặc định và bạn phải chuyển giá trị cho server_hostname. Nếu server_hostname là một chuỗi trống, việc khớp tên máy chủ sẽ bị vô hiệu hóa (đây là một rủi ro bảo mật nghiêm trọng, tạo điều kiện cho các cuộc tấn công trung gian tiềm ẩn).family, proto, flags là họ địa chỉ, giao thức và cờ tùy chọn được chuyển qua getaddrinfo() để phân giải host. Nếu được cung cấp, tất cả các giá trị này phải là số nguyên từ hằng số mô-đun
sockettương ứng.happy_eyeballs_delay, nếu được cung cấp, sẽ bật Happy Eyeballs cho kết nối này. Nó phải là một số dấu phẩy động biểu thị khoảng thời gian tính bằng giây để chờ một lần thử kết nối hoàn tất, trước khi bắt đầu lần thử tiếp theo một cách song song. Đây là "Độ trễ cố gắng kết nối" như được định nghĩa trong RFC 8305. Giá trị mặc định hợp lý được RFC đề xuất là
0.25(250 mili giây).interleave kiểm soát việc sắp xếp lại địa chỉ khi tên máy chủ phân giải thành nhiều địa chỉ IP. Nếu
0hoặc không được chỉ định, việc sắp xếp lại sẽ không được thực hiện và các địa chỉ sẽ được thử theo thứ tự được trả về bởigetaddrinfo(). Nếu một số nguyên dương được chỉ định, các địa chỉ sẽ được xen kẽ theo họ địa chỉ và số nguyên đã cho được hiểu là "Số họ địa chỉ đầu tiên" như được xác định trong RFC 8305. Mặc định là0nếu happy_eyeballs_delay không được chỉ định và1nếu có.sock, nếu được cung cấp, phải là một đối tượng
socket.sockethiện có, đã được kết nối để phương tiện vận chuyển sử dụng. Nếu sock được cung cấp thì không nên chỉ định host, port, family, proto, flags, happy_eyeballs_delay, interleave và local_addr.Ghi chú
Đối số sock chuyển quyền sở hữu ổ cắm sang phương tiện truyền tải được tạo. Để đóng socket, hãy gọi phương thức
close()của phương tiện vận chuyển.local_addr, nếu được cung cấp, là một bộ
(local_host, local_port)được sử dụng để liên kết ổ cắm cục bộ. local_host và local_port được tra cứu bằnggetaddrinfo(), tương tự như host và port.ssl_handshake_timeout là (đối với kết nối TLS) thời gian tính bằng giây để chờ quá trình bắt tay TLS hoàn tất trước khi hủy kết nối.
60.0giây nếuNone(mặc định).ssl_shutdown_timeout là thời gian tính bằng giây để chờ quá trình tắt SSL hoàn tất trước khi hủy kết nối.
30.0giây nếuNone(mặc định).all_errors xác định ngoại lệ nào được đưa ra khi không thể tạo kết nối. Theo mặc định, chỉ một
Exceptionduy nhất được nêu ra: ngoại lệ đầu tiên nếu chỉ có một hoặc tất cả các lỗi có cùng một thông báo hoặc mộtOSErrorduy nhất có các thông báo lỗi được kết hợp. Khiall_errorslàTrue, mộtExceptionGroupsẽ được đưa ra chứa tất cả các ngoại lệ (ngay cả khi chỉ có một ngoại lệ).
Thay đổi trong phiên bản 3.5: Đã thêm hỗ trợ cho SSL/TLS trong
ProactorEventLoop.Thay đổi trong phiên bản 3.6: Tùy chọn ổ cắm socket.TCP_NODELAY được đặt theo mặc định cho tất cả các kết nối TCP.
Thay đổi trong phiên bản 3.7: Đã thêm tham số ssl_handshake_timeout.
Thay đổi trong phiên bản 3.8: Đã thêm thông số happy_eyeballs_delay và interleave.
Thuật toán Happy Eyeballs: Thành công với máy chủ ngăn xếp kép. Khi đường dẫn và giao thức IPv4 của máy chủ đang hoạt động nhưng đường dẫn và giao thức IPv6 của máy chủ không hoạt động, ứng dụng máy khách xếp chồng kép sẽ gặp phải độ trễ kết nối đáng kể so với máy khách chỉ có IPv4. Điều này là không mong muốn vì nó khiến máy khách xếp chồng kép có trải nghiệm người dùng kém hơn. Tài liệu này chỉ định các yêu cầu đối với các thuật toán giúp giảm độ trễ mà người dùng có thể nhìn thấy này và cung cấp thuật toán.
Để biết thêm thông tin: https://datatracker.ietf.org/doc/html/rfc6555
Thay đổi trong phiên bản 3.11: Đã thêm tham số ssl_shutdown_timeout.
Thay đổi trong phiên bản 3.12: all_errors đã được thêm vào.
Xem thêm
Hàm
open_connection()là một hàm API thay thế cấp cao. Nó trả về một cặp (StreamReader,StreamWriter) có thể được sử dụng trực tiếp trong mã async/await.
- async loop.create_datagram_endpoint(protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0, reuse_port=None, allow_broadcast=None, sock=None)¶
Tạo kết nối datagram.
Họ socket có thể là
AF_INET,AF_INET6hoặcAF_UNIX, tùy thuộc vào host (hoặc đối số family, nếu được cung cấp).Loại ổ cắm sẽ là
SOCK_DGRAM.protocol_factory phải là một phương thức có thể gọi được và trả về việc triển khai protocol.
Một bộ
(transport, protocol)được trả về thành công.Các lập luận khác:
local_addr, nếu được cung cấp, là một bộ
(local_host, local_port)được sử dụng để liên kết ổ cắm cục bộ. local_host và local_port được tra cứu bằnggetaddrinfo().Ghi chú
Trên Windows, khi sử dụng vòng lặp sự kiện thước đo với
local_addr=None,OSErrorvớierrno.WSAEINVALsẽ được nâng lên khi chạy nó.remote_addr, nếu được cung cấp, là một bộ
(remote_host, remote_port)được sử dụng để kết nối ổ cắm với một địa chỉ từ xa. remote_host và remote_port được tra cứu bằnggetaddrinfo().family, proto, flags là họ địa chỉ, giao thức và cờ tùy chọn được chuyển tới
getaddrinfo()để phân giải host. Nếu được cung cấp, tất cả các giá trị này phải là số nguyên từ hằng số mô-đunsockettương ứng.reuse_port yêu cầu kernel cho phép điểm cuối này được liên kết với cùng một cổng mà các điểm cuối hiện có khác được liên kết, miễn là tất cả chúng đều đặt cờ này khi được tạo. Tùy chọn này không được hỗ trợ trên Windows và một số Unix. Nếu hằng số socket.SO_REUSEPORT không được xác định thì khả năng này không được hỗ trợ.
allow_broadcast yêu cầu kernel cho phép điểm cuối này gửi tin nhắn đến địa chỉ quảng bá.
sock có thể được chỉ định tùy ý để sử dụng một đối tượng
socket.socketcó sẵn, đã được kết nối để vận chuyển sử dụng. Nếu được chỉ định, nên bỏ qua local_addr và remote_addr (phải làNone).Ghi chú
Đối số sock chuyển quyền sở hữu ổ cắm sang phương tiện truyền tải được tạo. Để đóng socket, hãy gọi phương thức
close()của phương tiện vận chuyển.
Xem ví dụ về UDP echo client protocol và UDP echo server protocol.
Thay đổi trong phiên bản 3.4.4: Các thông số family, proto, flags, reuse_address, reuse_port, allow_broadcast và sock đã được thêm vào.
Thay đổi trong phiên bản 3.8: Đã thêm hỗ trợ cho Windows.
Thay đổi trong phiên bản 3.8.1: Tham số reuse_address không còn được hỗ trợ vì việc sử dụng socket.SO_REUSEADDR gây ra mối lo ngại đáng kể về bảo mật cho UDP. Việc chuyển
reuse_address=Truemột cách rõ ràng sẽ tạo ra một ngoại lệ.Khi nhiều quy trình có UID khác nhau gán các ổ cắm cho một địa chỉ ổ cắm UDP giống hệt nhau với
SO_REUSEADDR, các gói đến có thể được phân phối ngẫu nhiên giữa các ổ cắm.Đối với các nền tảng được hỗ trợ, reuse_port có thể được sử dụng để thay thế cho chức năng tương tự. Với reuse_port, socket.SO_REUSEPORT được sử dụng thay thế, điều này đặc biệt ngăn chặn các quá trình có UID khác nhau gán các ổ cắm cho cùng một địa chỉ ổ cắm.
Thay đổi trong phiên bản 3.11: Tham số reuse_address, bị tắt kể từ Python 3.8.1, 3.7.6 và 3.6.10, đã bị xóa hoàn toàn.
- async loop.create_unix_connection(protocol_factory, path=None, *, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)¶
Tạo kết nối Unix.
Họ socket sẽ là
AF_UNIX; loại ổ cắm sẽ làSOCK_STREAM.Một bộ
(transport, protocol)được trả về thành công.path là tên của ổ cắm tên miền Unix và được yêu cầu, trừ khi tham số sock được chỉ định. Hỗ trợ các ổ cắm Unix trừu tượng, đường dẫn
str,bytesvàPath.Xem tài liệu về phương pháp
loop.create_connection()để biết thông tin về các đối số của phương pháp này.sẵn có: Unix.
Thay đổi trong phiên bản 3.7: Đã thêm tham số ssl_handshake_timeout. Tham số path bây giờ có thể là path-like object.
Thay đổi trong phiên bản 3.11: Đã thêm tham số ssl_shutdown_timeout.
Tạo máy chủ mạng¶
- async loop.create_server(protocol_factory, host=None, port=None, *, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None, reuse_port=None, keep_alive=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True)¶
Tạo một máy chủ TCP (loại ổ cắm
SOCK_STREAM) nghe trên port của địa chỉ host.Trả về một đối tượng
Server.Lập luận:
protocol_factory phải là một phương thức có thể gọi được và trả về việc triển khai protocol.
Tham số host có thể được đặt thành một số loại xác định nơi máy chủ sẽ lắng nghe:
Nếu host là một chuỗi, máy chủ TCP được liên kết với một giao diện mạng duy nhất được chỉ định bởi host.
Nếu host là một chuỗi các chuỗi, máy chủ TCP sẽ bị ràng buộc với tất cả các giao diện mạng được chỉ định bởi chuỗi đó.
Nếu host là một chuỗi trống hoặc
None, tất cả các giao diện đều được giả định và một danh sách nhiều ổ cắm sẽ được trả về (rất có thể một ổ cắm cho IPv4 và một ổ cắm khác cho IPv6).
Tham số port có thể được đặt để chỉ định cổng nào máy chủ sẽ nghe. Nếu
0hoặcNone(mặc định), một cổng ngẫu nhiên không được sử dụng sẽ được chọn (lưu ý rằng nếu host phân giải thành nhiều giao diện mạng thì một cổng ngẫu nhiên khác sẽ được chọn cho mỗi giao diện).family có thể được đặt thành
socket.AF_INEThoặcAF_INET6để buộc ổ cắm sử dụng IPv4 hoặc IPv6. Nếu không được đặt, family sẽ được xác định từ tên máy chủ (mặc định làAF_UNSPEC).flags là mặt nạ bit cho
getaddrinfo().sock có thể được chỉ định tùy ý để sử dụng đối tượng ổ cắm có sẵn. Nếu được chỉ định thì không được chỉ định host và port.
Ghi chú
Đối số sock chuyển quyền sở hữu socket sang máy chủ đã tạo. Để đóng socket, hãy gọi phương thức
close()của máy chủ.backlog là số lượng kết nối được xếp hàng tối đa được chuyển tới
listen()(mặc định là 100).ssl có thể được đặt thành phiên bản
SSLContextđể bật TLS qua các kết nối được chấp nhận.reuse_address yêu cầu kernel sử dụng lại ổ cắm cục bộ ở trạng thái
TIME_WAITmà không cần đợi hết thời gian chờ tự nhiên. Nếu không được chỉ định sẽ tự động được đặt thànhTruetrên Unix.reuse_port yêu cầu kernel cho phép điểm cuối này được liên kết với cùng một cổng mà các điểm cuối hiện có khác được liên kết, miễn là tất cả chúng đều đặt cờ này khi được tạo. Tùy chọn này không được hỗ trợ trên Windows.
keep_alive được đặt thành
Truesẽ duy trì kết nối hoạt động bằng cách cho phép truyền tin nhắn định kỳ.
Thay đổi trong phiên bản 3.13: Đã thêm tham số keep_alive.
ssl_handshake_timeout là (đối với máy chủ TLS) thời gian tính bằng giây để chờ quá trình bắt tay TLS hoàn tất trước khi hủy kết nối.
60.0giây nếuNone(mặc định).ssl_shutdown_timeout là thời gian tính bằng giây để chờ quá trình tắt SSL hoàn tất trước khi hủy kết nối.
30.0giây nếuNone(mặc định).start_serving được đặt thành
True(mặc định) khiến máy chủ đã tạo bắt đầu chấp nhận kết nối ngay lập tức. Khi được đặt thànhFalse, người dùng nên đợi trênServer.start_serving()hoặcServer.serve_forever()để yêu cầu máy chủ bắt đầu chấp nhận kết nối.
Thay đổi trong phiên bản 3.5: Đã thêm hỗ trợ cho SSL/TLS trong
ProactorEventLoop.Thay đổi trong phiên bản 3.5.1: Tham số host có thể là một chuỗi các chuỗi.
Thay đổi trong phiên bản 3.6: Đã thêm thông số ssl_handshake_timeout và start_serving. Tùy chọn ổ cắm socket.TCP_NODELAY được đặt theo mặc định cho tất cả các kết nối TCP.
Thay đổi trong phiên bản 3.11: Đã thêm tham số ssl_shutdown_timeout.
Xem thêm
Hàm
start_server()là một hàm API thay thế cấp cao hơn trả về một cặpStreamReadervàStreamWritercó thể được sử dụng trong mã async/await.
- async loop.create_unix_server(protocol_factory, path=None, *, sock=None, backlog=100, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None, start_serving=True, cleanup_socket=True)¶
Tương tự như
loop.create_server()nhưng hoạt động với dòng ổ cắmAF_UNIX.path là tên của ổ cắm tên miền Unix và được yêu cầu, trừ khi đối số sock được cung cấp. Hỗ trợ các ổ cắm Unix trừu tượng, đường dẫn
str,bytesvàPath.Nếu cleanup_socket là đúng thì ổ cắm Unix sẽ tự động bị xóa khỏi hệ thống tập tin khi máy chủ đóng, trừ khi ổ cắm đó đã được thay thế sau khi máy chủ được tạo.
Xem tài liệu về phương pháp
loop.create_server()để biết thông tin về các đối số của phương pháp này.sẵn có: Unix.
Thay đổi trong phiên bản 3.7: Đã thêm thông số ssl_handshake_timeout và start_serving. Tham số path hiện có thể là đối tượng
Path.Thay đổi trong phiên bản 3.11: Đã thêm tham số ssl_shutdown_timeout.
Thay đổi trong phiên bản 3.13: Đã thêm tham số cleanup_socket.
- async loop.connect_accepted_socket(protocol_factory, sock, *, ssl=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)¶
Gói một kết nối đã được chấp nhận vào một cặp truyền tải/giao thức.
Phương pháp này có thể được sử dụng bởi các máy chủ chấp nhận kết nối bên ngoài asyncio nhưng sử dụng asyncio để xử lý chúng.
Thông số:
protocol_factory phải là một phương thức có thể gọi được và trả về việc triển khai protocol.
sock là một đối tượng socket có sẵn được trả về từ
socket.accept.Ghi chú
Đối số sock chuyển quyền sở hữu ổ cắm sang phương tiện truyền tải được tạo. Để đóng socket, hãy gọi phương thức
close()của phương tiện vận chuyển.ssl có thể được đặt thành
SSLContextđể bật SSL qua các kết nối được chấp nhận.ssl_handshake_timeout là (đối với kết nối SSL) thời gian tính bằng giây để chờ quá trình bắt tay SSL hoàn tất trước khi hủy kết nối.
60.0giây nếuNone(mặc định).ssl_shutdown_timeout là thời gian tính bằng giây để chờ quá trình tắt SSL hoàn tất trước khi hủy kết nối.
30.0giây nếuNone(mặc định).
Trả về một cặp
(transport, protocol).Added in version 3.5.3.
Thay đổi trong phiên bản 3.7: Đã thêm tham số ssl_handshake_timeout.
Thay đổi trong phiên bản 3.11: Đã thêm tham số ssl_shutdown_timeout.
Truyền tập tin¶
- async loop.sendfile(transport, file, offset=0, count=None, *, fallback=True)¶
Gửi file qua transport. Trả về tổng số byte đã gửi.
Phương pháp sử dụng
os.sendfile()hiệu suất cao nếu có.file phải là đối tượng tệp thông thường được mở ở chế độ nhị phân.
offset cho biết bắt đầu đọc tệp từ đâu. Nếu được chỉ định, count là tổng số byte cần truyền thay vì gửi tệp cho đến khi đạt được EOF. Vị trí tệp luôn được cập nhật, ngay cả khi phương pháp này phát sinh lỗi và
file.tell()có thể được sử dụng để lấy số byte thực tế được gửi.fallback được đặt thành
Truekhiến asyncio đọc và gửi tệp theo cách thủ công khi nền tảng không hỗ trợ lệnh gọi hệ thống sendfile (ví dụ: ổ cắm Windows hoặc SSL trên Unix).Tăng
SendfileNotAvailableErrornếu hệ thống không hỗ trợ tòa nhà sendfile và fallback làFalse.Added in version 3.7.
nâng cấp TLS¶
- async loop.start_tls(transport, protocol, sslcontext, *, server_side=False, server_hostname=None, ssl_handshake_timeout=None, ssl_shutdown_timeout=None)¶
Nâng cấp kết nối dựa trên truyền tải hiện có lên TLS.
Tạo một phiên bản bộ mã hóa/giải mã TLS và chèn nó vào giữa transport và protocol. Bộ mã hóa/bộ giải mã thực hiện cả giao thức hướng tới transport và truyền tải hướng tới protocol.
Trả về phiên bản hai giao diện đã tạo. Sau await, protocol phải ngừng sử dụng transport ban đầu và chỉ liên lạc với đối tượng được trả về vì bộ mã hóa lưu trữ dữ liệu phía protocol và thỉnh thoảng trao đổi các gói phiên TLS bổ sung với transport.
Trong một số trường hợp (ví dụ: khi quá trình vận chuyển đã qua đã đóng), điều này có thể trả về
None.Thông số:
transport và protocol các trường hợp mà các phương thức như
create_server()vàcreate_connection()trả về.sslcontext: phiên bản được định cấu hình của
SSLContext.server_side vượt qua
Truekhi kết nối phía máy chủ đang được nâng cấp (giống như kết nối được tạo bởicreate_server()).server_hostname: đặt hoặc ghi đè tên máy chủ mà chứng chỉ của máy chủ mục tiêu sẽ được so khớp.
ssl_handshake_timeout là (đối với kết nối TLS) thời gian tính bằng giây để chờ quá trình bắt tay TLS hoàn tất trước khi hủy kết nối.
60.0giây nếuNone(mặc định).ssl_shutdown_timeout là thời gian tính bằng giây để chờ quá trình tắt SSL hoàn tất trước khi hủy kết nối.
30.0giây nếuNone(mặc định).
Added in version 3.7.
Thay đổi trong phiên bản 3.11: Đã thêm tham số ssl_shutdown_timeout.
Xem mô tả tập tin¶
- loop.add_reader(fd, callback, *args)¶
Bắt đầu theo dõi bộ mô tả tệp fd để biết khả năng đọc và gọi callback với các đối số được chỉ định khi fd có sẵn để đọc.
Mọi lệnh gọi lại hiện có đã đăng ký cho fd đều bị hủy và được thay thế bằng callback.
- loop.remove_reader(fd)¶
Dừng theo dõi bộ mô tả tệp fd để biết khả năng đọc. Trả về
Truenếu fd trước đó đã được theo dõi để đọc.
- loop.add_writer(fd, callback, *args)¶
Bắt đầu theo dõi bộ mô tả tệp fd để biết khả năng ghi và gọi callback với các đối số được chỉ định args khi fd có sẵn để ghi.
Mọi lệnh gọi lại hiện có đã đăng ký cho fd đều bị hủy và được thay thế bằng callback.
Sử dụng
functools.partial()to pass keyword arguments đến callback.
- loop.remove_writer(fd)¶
Dừng theo dõi bộ mô tả tệp fd để biết khả năng ghi. Trả về
Truenếu fd trước đó đã được theo dõi để ghi.
Xem thêm phần Platform Support để biết một số hạn chế của các phương pháp này.
Làm việc trực tiếp với các đối tượng socket¶
Nhìn chung, việc triển khai giao thức sử dụng các API dựa trên truyền tải như loop.create_connection() và loop.create_server() sẽ nhanh hơn so với các triển khai hoạt động trực tiếp với ổ cắm. Tuy nhiên, có một số trường hợp sử dụng khi hiệu suất không quan trọng và làm việc trực tiếp với các đối tượng socket sẽ thuận tiện hơn.
- async loop.sock_recv(sock, nbytes)¶
Nhận tới nbytes từ sock. Phiên bản không đồng bộ của
socket.recv().Trả về dữ liệu đã nhận dưới dạng đối tượng byte.
sock phải là ổ cắm không chặn.
Thay đổi trong phiên bản 3.7: Mặc dù phương thức này luôn được ghi lại dưới dạng phương thức coroutine, các bản phát hành trước Python 3.7 đều trả về
Future. Vì Python 3.7 nên đây là phương thứcasync def.
- async loop.sock_recv_into(sock, buf)¶
Nhận dữ liệu từ sock vào bộ đệm buf. Được mô hình hóa theo phương pháp chặn
socket.recv_into().Trả về số byte được ghi vào bộ đệm.
sock phải là ổ cắm không chặn.
Added in version 3.7.
- async loop.sock_recvfrom(sock, bufsize)¶
Nhận datagram lên tới bufsize từ sock. Phiên bản không đồng bộ của
socket.recvfrom().Trả về một bộ dữ liệu (dữ liệu đã nhận, địa chỉ từ xa).
sock phải là ổ cắm không chặn.
Added in version 3.11.
- async loop.sock_recvfrom_into(sock, buf, nbytes=0)¶
Nhận datagram lên tới nbytes từ sock vào buf. Phiên bản không đồng bộ của
socket.recvfrom_into().Trả về một bộ dữ liệu (số byte nhận được, địa chỉ từ xa).
sock phải là ổ cắm không chặn.
Added in version 3.11.
- async loop.sock_sendall(sock, data)¶
Gửi data đến ổ cắm sock. Phiên bản không đồng bộ của
socket.sendall().Phương thức này tiếp tục gửi đến ổ cắm cho đến khi tất cả dữ liệu trong data đã được gửi hoặc xảy ra lỗi.
Noneđược trả về thành công. Khi có lỗi, một ngoại lệ được đưa ra. Ngoài ra, không có cách nào để xác định lượng dữ liệu, nếu có, đã được xử lý thành công ở đầu nhận của kết nối.sock phải là ổ cắm không chặn.
Thay đổi trong phiên bản 3.7: Mặc dù phương thức này luôn được ghi lại dưới dạng phương thức coroutine, nhưng trước Python 3.7, nó trả về
Future. Kể từ Python 3.7, đây là phương thứcasync def.
- async loop.sock_sendto(sock, data, address)¶
Gửi một datagram từ sock đến address. Phiên bản không đồng bộ của
socket.sendto().Trả về số byte đã gửi.
sock phải là ổ cắm không chặn.
Added in version 3.11.
- async loop.sock_connect(sock, address)¶
Kết nối sock với ổ cắm từ xa tại address.
Phiên bản không đồng bộ của
socket.connect().sock phải là ổ cắm không chặn.
Thay đổi trong phiên bản 3.5.2:
addresskhông cần phải giải quyết nữa.sock_connectsẽ thử kiểm tra xem address đã được giải quyết chưa bằng cách gọisocket.inet_pton(). Nếu không,loop.getaddrinfo()sẽ được sử dụng để giải quyết address.Xem thêm
- async loop.sock_accept(sock)¶
Chấp nhận một kết nối. Được mô hình hóa theo phương pháp chặn
socket.accept().Ổ cắm phải được liên kết với một địa chỉ và lắng nghe các kết nối. Giá trị trả về là một cặp
(conn, address)trong đó conn là đối tượng ổ cắm new có thể sử dụng để gửi và nhận dữ liệu trên kết nối và address là địa chỉ được liên kết với ổ cắm ở đầu bên kia của kết nối.sock phải là ổ cắm không chặn.
Thay đổi trong phiên bản 3.7: Mặc dù phương thức này luôn được ghi lại dưới dạng phương thức coroutine, nhưng trước Python 3.7, nó trả về
Future. Kể từ Python 3.7, đây là phương thứcasync def.Xem thêm
- async loop.sock_sendfile(sock, file, offset=0, count=None, *, fallback=True)¶
Gửi tệp bằng
os.sendfilehiệu suất cao nếu có thể. Trả về tổng số byte đã gửi.Phiên bản không đồng bộ của
socket.sendfile().sock phải là
socket.SOCK_STREAMsocketkhông chặn.file phải là đối tượng tệp thông thường mở ở chế độ nhị phân.
offset cho biết bắt đầu đọc tệp từ đâu. Nếu được chỉ định, count là tổng số byte cần truyền thay vì gửi tệp cho đến khi đạt được EOF. Vị trí tệp luôn được cập nhật, ngay cả khi phương pháp này phát sinh lỗi và
file.tell()có thể được sử dụng để lấy số byte thực tế được gửi.fallback, khi được đặt thành
True, sẽ khiến asyncio đọc và gửi tệp theo cách thủ công khi nền tảng không hỗ trợ tòa nhà sendfile (ví dụ: ổ cắm Windows hoặc SSL trên Unix).Tăng
SendfileNotAvailableErrornếu hệ thống không hỗ trợ sendfile syscall và fallback làFalse.sock phải là ổ cắm không chặn.
Added in version 3.7.
DNS¶
- async loop.getaddrinfo(host, port, *, family=0, type=0, proto=0, flags=0)¶
Phiên bản không đồng bộ của
socket.getaddrinfo().
- async loop.getnameinfo(sockaddr, flags=0)¶
Phiên bản không đồng bộ của
socket.getnameinfo().
Ghi chú
Cả getaddrinfo và getnameinfo đều sử dụng nội bộ các phiên bản đồng bộ của chúng thông qua trình thực thi nhóm luồng mặc định của vòng lặp. Khi trình thực thi này bão hòa, các phương pháp này có thể gặp phải sự chậm trễ mà các thư viện mạng cấp cao hơn có thể báo cáo là thời gian chờ tăng lên. Để giảm thiểu điều này, hãy cân nhắc sử dụng trình thực thi tùy chỉnh cho các tác vụ khác của người dùng hoặc đặt trình thực thi mặc định với số lượng nhân viên lớn hơn.
Thay đổi trong phiên bản 3.7: Cả hai phương thức getaddrinfo và getnameinfo đều luôn được ghi lại để trả về một coroutine, nhưng trước Python 3.7, trên thực tế, chúng đã trả về các đối tượng asyncio.Future. Bắt đầu với Python 3.7, cả hai phương thức đều là coroutine.
Làm việc với đường ống¶
- async loop.connect_read_pipe(protocol_factory, pipe)¶
Đăng ký phần cuối đọc của pipe trong vòng lặp sự kiện.
protocol_factory phải là một phương thức có thể gọi được và trả về việc triển khai asyncio protocol.
pipe là file-like object.
Trả về cặp
(transport, protocol), trong đó transport hỗ trợ giao diệnReadTransportvà protocol là một đối tượng được protocol_factory khởi tạo.Với vòng lặp sự kiện
SelectorEventLoop, pipe được đặt ở chế độ không chặn.
- async loop.connect_write_pipe(protocol_factory, pipe)¶
Đăng ký phần cuối ghi của pipe trong vòng lặp sự kiện.
protocol_factory phải là một phương thức có thể gọi được và trả về việc triển khai asyncio protocol.
pipe là file-like object.
Trả về cặp
(transport, protocol), trong đó transport hỗ trợ giao diệnWriteTransportvà protocol là một đối tượng được protocol_factory khởi tạo.Với vòng lặp sự kiện
SelectorEventLoop, pipe được đặt ở chế độ không chặn.
Ghi chú
SelectorEventLoop không hỗ trợ các phương pháp trên trên Windows. Sử dụng ProactorEventLoop thay thế cho Windows.
Xem thêm
Phương pháp loop.subprocess_exec() và loop.subprocess_shell().
Tín hiệu Unix¶
- loop.add_signal_handler(signum, callback, *args)¶
Đặt callback làm trình xử lý tín hiệu signum, chuyển args làm đối số vị trí.
Lệnh gọi lại sẽ được loop gọi ra, cùng với các lệnh gọi lại được xếp hàng khác và các coroutine có thể chạy của vòng lặp sự kiện đó. Không giống như các trình xử lý tín hiệu được đăng ký bằng
signal.signal(), lệnh gọi lại được đăng ký với chức năng này được phép tương tác với vòng lặp sự kiện.Tăng
ValueErrornếu số tín hiệu không hợp lệ hoặc không thể bắt được. TăngRuntimeErrornếu có vấn đề khi thiết lập trình xử lý.Sử dụng
functools.partial()to pass keyword arguments đến callback.Giống như
signal.signal(), hàm này phải được gọi trong luồng chính.
- loop.remove_signal_handler(sig)¶
Loại bỏ trình xử lý tín hiệu sig.
Trả về
Truenếu bộ xử lý tín hiệu đã bị xóa hoặcFalsenếu không có bộ xử lý nào được đặt cho tín hiệu đã cho.sẵn có: Unix.
Xem thêm
Mô-đun signal.
Thực thi mã trong nhóm luồng hoặc nhóm quy trình¶
- awaitable loop.run_in_executor(executor, func, *args)¶
Sắp xếp để func được gọi trong trình thực thi đã chỉ định chuyển args làm đối số vị trí.
Đối số executor phải là một phiên bản
concurrent.futures.Executor. Trình thực thi mặc định được sử dụng nếu executor làNone. Trình thực thi mặc định có thể được đặt bởiloop.set_default_executor(), nếu không,concurrent.futures.ThreadPoolExecutorsẽ được khởi tạo lười biếng và đượcrun_in_executor()sử dụng nếu cần.Ví dụ:
nhập asyncio nhập đồng thời.futures chặn chắc chắn_io(): Các hoạt động # File (chẳng hạn như ghi nhật ký) có thể chặn Vòng lặp # event: chạy chúng trong nhóm luồng. với open('/dev/urandom', 'rb') là f: trả về f.read(100) def cpu_bound(): Hoạt động # CPU-bound sẽ chặn vòng lặp sự kiện: # in nói chung thì nên chạy chúng trong một hồ bơi # process. trả về tổng(i * i cho i trong phạm vi (10 ** 7)) async def main(): vòng lặp = asyncio.get_running_loop() ## Options: # 1. Chạy trong trình thực thi của vòng lặp mặc định: kết quả = đang chờ loop.run_in_executor( Không, chặn_io) print('nhóm luồng mặc định', kết quả) # 2. Chạy trong nhóm chủ đề tùy chỉnh: với concurrent.futures.ThreadPoolExecutor() dưới dạng nhóm: kết quả = đang chờ loop.run_in_executor( nhóm, chặn_io) print('nhóm chủ đề tùy chỉnh', kết quả) # 3. Chạy trong nhóm quy trình tùy chỉnh: với concurrent.futures.ProcessPoolExecutor() dưới dạng nhóm: kết quả = đang chờ loop.run_in_executor( nhóm, cpu_bound) print('nhóm quy trình tùy chỉnh', kết quả) # 4. Chạy trong nhóm trình thông dịch tùy chỉnh: với concurrent.futures.InterpreterPoolExecutor() dưới dạng nhóm: kết quả = đang chờ loop.run_in_executor( nhóm, cpu_bound) print('nhóm thông dịch viên tùy chỉnh', kết quả) nếu __name__ == '__main__': asyncio.run(chính())
Lưu ý rằng cần phải có bộ bảo vệ điểm vào (
if __name__ == '__main__') cho tùy chọn 3 do đặc thù củamultiprocessing, đượcProcessPoolExecutorsử dụng. Xem Safe importing of main module.Phương thức này trả về một đối tượng
asyncio.Future.Sử dụng
functools.partial()to pass keyword arguments đến func.Thay đổi trong phiên bản 3.5.3:
loop.run_in_executor()không còn định cấu hìnhmax_workerscủa trình thực thi nhóm luồng mà nó tạo ra nữa, thay vào đó, hãy để trình thực thi nhóm luồng (ThreadPoolExecutor) thiết lập mặc định.
- loop.set_default_executor(executor)¶
Đặt executor làm trình thực thi mặc định được
run_in_executor()sử dụng. executor phải là một phiên bản củaThreadPoolExecutor, bao gồmInterpreterPoolExecutor.Thay đổi trong phiên bản 3.11: executor phải là một phiên bản của
ThreadPoolExecutor.
Lỗi xử lý API¶
Cho phép tùy chỉnh cách xử lý các ngoại lệ trong vòng lặp sự kiện.
- loop.set_exception_handler(handler)¶
Đặt handler làm trình xử lý ngoại lệ vòng lặp sự kiện mới.
Nếu handler là
None, trình xử lý ngoại lệ mặc định sẽ được đặt. Mặt khác, handler phải là một đối tượng có thể gọi được với chữ ký khớp với(loop, context), trong đólooplà một tham chiếu đến vòng lặp sự kiện đang hoạt động vàcontextlà một đối tượngdictchứa các chi tiết về ngoại lệ (xem tài liệu vềcall_exception_handler()để biết chi tiết về ngữ cảnh).Nếu trình xử lý được gọi thay mặt cho
TaskhoặcHandle, thì nó sẽ chạy trongcontextvars.Contextcủa tác vụ hoặc bộ xử lý gọi lại đó.Thay đổi trong phiên bản 3.12: Trình xử lý có thể được gọi trong
Contextcủa tác vụ hoặc xử lý nơi bắt nguồn ngoại lệ.
- loop.get_exception_handler()¶
Trả về trình xử lý ngoại lệ hiện tại hoặc
Nonenếu không có trình xử lý ngoại lệ tùy chỉnh nào được đặt.Added in version 3.5.2.
- loop.default_exception_handler(context)¶
Trình xử lý ngoại lệ mặc định.
Điều này được gọi khi xảy ra ngoại lệ và không có trình xử lý ngoại lệ nào được đặt. Điều này có thể được gọi bởi một trình xử lý ngoại lệ tùy chỉnh muốn trì hoãn hành vi xử lý mặc định.
Tham số context có ý nghĩa tương tự như trong
call_exception_handler().
- loop.call_exception_handler(context)¶
Gọi trình xử lý ngoại lệ của vòng lặp sự kiện hiện tại.
context là một đối tượng
dictchứa các khóa sau (các khóa mới có thể được giới thiệu trong các phiên bản Python trong tương lai):'tin nhắn': Thông báo lỗi;
'ngoại lệ' (tùy chọn): Đối tượng ngoại lệ;
'tương lai' (tùy chọn): phiên bản
asyncio.Future;'nhiệm vụ' (tùy chọn): phiên bản
asyncio.Task;'xử lý' (tùy chọn): phiên bản
asyncio.Handle;'giao thức' (tùy chọn): phiên bản Protocol;
'vận chuyển' (tùy chọn): phiên bản Transport;
'socket' (tùy chọn): phiên bản
socket.socket;'source_traceback' (tùy chọn): Truy nguyên nguồn;
'handle_traceback' (tùy chọn): Truy nguyên dấu vết của bộ điều khiển;
- 'asyncgen' (tùy chọn): Trình tạo không đồng bộ gây ra
ngoại lệ.
Ghi chú
Phương thức này không nên bị quá tải trong các vòng lặp sự kiện được phân lớp. Để xử lý ngoại lệ tùy chỉnh, hãy sử dụng phương pháp
set_exception_handler().
Bật chế độ gỡ lỗi¶
- loop.get_debug()¶
Nhận chế độ gỡ lỗi (
bool) của vòng lặp sự kiện.Giá trị mặc định là
Truenếu biến môi trườngPYTHONASYNCIODEBUGđược đặt thành một chuỗi không trống, nếu không thìFalse.
- loop.set_debug(enabled: bool)¶
Đặt chế độ gỡ lỗi của vòng lặp sự kiện.
Thay đổi trong phiên bản 3.7: Zz000zz mới hiện cũng có thể được sử dụng để kích hoạt chế độ gỡ lỗi.
- loop.slow_callback_duration¶
Thuộc tính này có thể được sử dụng để đặt thời lượng thực hiện tối thiểu tính bằng giây được coi là "chậm". Khi chế độ gỡ lỗi được bật, lệnh gọi lại "chậm" sẽ được ghi lại.
Giá trị mặc định là 100 mili giây.
Xem thêm
Z000zz.
Chạy các tiến trình con¶
Các phương pháp được mô tả trong tiểu mục này là ở mức độ thấp. Trong mã async/await thông thường, hãy cân nhắc sử dụng các hàm tiện lợi asyncio.create_subprocess_shell() và asyncio.create_subprocess_exec() cấp cao để thay thế.
Ghi chú
Trên Windows, vòng lặp sự kiện mặc định ProactorEventLoop hỗ trợ các quy trình con, trong khi SelectorEventLoop thì không. Xem Subprocess Support on Windows để biết chi tiết.
- async loop.subprocess_exec(protocol_factory, *args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)¶
Tạo một quy trình con từ một hoặc nhiều đối số chuỗi được chỉ định bởi args.
args phải là danh sách các chuỗi được đại diện bởi:
str;hoặc
bytes, được mã hóa thành filesystem encoding.
Chuỗi đầu tiên chỉ định chương trình có thể thực thi được và các chuỗi còn lại chỉ định các đối số. Cùng với nhau, các đối số chuỗi tạo thành
argvcủa chương trình.Điều này tương tự như lớp
subprocess.Popencủa thư viện chuẩn được gọi bằngshell=Falsevà danh sách các chuỗi được truyền làm đối số đầu tiên; tuy nhiên, trong đóPopennhận một đối số duy nhất là danh sách các chuỗi, thì subprocess_exec nhận nhiều đối số chuỗi.Zz001zz phải là một lớp có thể gọi được và trả về một lớp con của lớp
asyncio.SubprocessProtocol.Các thông số khác:
stdin có thể là một trong số này:
một đối tượng giống như tập tin
một bộ mô tả tệp hiện có (một số nguyên dương), ví dụ như những bộ mô tả được tạo bằng
os.pipe()hằng số
subprocess.PIPE(mặc định) sẽ tạo một đường ống mới và kết nối nó,giá trị
Nonesẽ làm cho quy trình con kế thừa bộ mô tả tệp từ quy trình nàyhằng số
subprocess.DEVNULLcho biết tệpos.devnullđặc biệt sẽ được sử dụng
stdout có thể là một trong số này:
một đối tượng giống như tập tin
hằng số
subprocess.PIPE(mặc định) sẽ tạo một đường ống mới và kết nối nó,giá trị
Nonesẽ làm cho quy trình con kế thừa bộ mô tả tệp từ quy trình nàyhằng số
subprocess.DEVNULLcho biết tệpos.devnullđặc biệt sẽ được sử dụng
stderr có thể là một trong số này:
một đối tượng giống như tập tin
hằng số
subprocess.PIPE(mặc định) sẽ tạo một đường ống mới và kết nối nó,giá trị
Nonesẽ làm cho quy trình con kế thừa bộ mô tả tệp từ quy trình nàyhằng số
subprocess.DEVNULLcho biết tệpos.devnullđặc biệt sẽ được sử dụnghằng số
subprocess.STDOUTsẽ kết nối luồng lỗi tiêu chuẩn với luồng đầu ra tiêu chuẩn của quy trình
Tất cả các đối số từ khóa khác được chuyển đến
subprocess.Popenmà không cần giải thích, ngoại trừ bufsize, universal_newlines, shell, text, encoding và errors, những đối số này hoàn toàn không được chỉ định.Quy trình con
asyncioAPI không hỗ trợ giải mã các luồng dưới dạng văn bản.bytes.decode()có thể được sử dụng để chuyển đổi các byte được trả về từ luồng thành văn bản.
Nếu một đối tượng giống như tệp được truyền dưới dạng stdin, stdout hoặc stderr đại diện cho một đường ống thì phía bên kia của đường ống này phải được đăng ký bằng
connect_write_pipe()hoặcconnect_read_pipe()để sử dụng với vòng lặp sự kiện.Xem hàm tạo của lớp
subprocess.Popenđể biết tài liệu về các đối số khác.Trả về một cặp
(transport, protocol), trong đó transport tuân theo lớp cơ sởasyncio.SubprocessTransportvà protocol là một đối tượng được khởi tạo bởi protocol_factory.Nếu quá trình vận chuyển bị đóng hoặc bị thu gom rác, tiến trình con sẽ bị hủy nếu nó vẫn đang chạy.
- async loop.subprocess_shell(protocol_factory, cmd, *, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)¶
Tạo một quy trình con từ cmd, có thể là chuỗi
strhoặcbytesđược mã hóa thành filesystem encoding, sử dụng cú pháp "shell" của nền tảng.Điều này tương tự như lớp
subprocess.Popentrong thư viện chuẩn được gọi bằngshell=True.Zz001zz phải là một lớp có thể gọi được và trả về một lớp con của lớp
SubprocessProtocol.Xem
subprocess_exec()để biết thêm chi tiết về các đối số còn lại.Trả về một cặp
(transport, protocol), trong đó transport tuân theo lớp cơ sởSubprocessTransportvà protocol là một đối tượng được khởi tạo bởi protocol_factory.Nếu quá trình vận chuyển bị đóng hoặc bị thu gom rác, tiến trình con sẽ bị hủy nếu nó vẫn đang chạy.
Ghi chú
Trách nhiệm của ứng dụng là đảm bảo rằng tất cả khoảng trắng và ký tự đặc biệt đều được trích dẫn một cách thích hợp để tránh các lỗ hổng shell injection. Hàm shlex.quote() có thể được sử dụng để thoát khoảng trắng và các ký tự đặc biệt trong chuỗi sẽ được sử dụng để xây dựng các lệnh shell một cách chính xác.
Điều khiển gọi lại¶
- class asyncio.Handle¶
Đối tượng trình bao bọc gọi lại được trả về bởi
loop.call_soon(),loop.call_soon_threadsafe().- get_context()¶
Trả về đối tượng
contextvars.Contextđược liên kết với tay cầm.Added in version 3.12.
- cancel()¶
Hủy cuộc gọi lại. Nếu lệnh gọi lại đã bị hủy hoặc được thực thi thì phương thức này không có hiệu lực.
- cancelled()¶
Trả về
Truenếu cuộc gọi lại bị hủy.Added in version 3.7.
- class asyncio.TimerHandle¶
Đối tượng trình bao bọc gọi lại được trả về bởi
loop.call_later()vàloop.call_at().Lớp này là một lớp con của
Handle.- when()¶
Trả về thời gian gọi lại theo lịch trình là
floatgiây.Thời gian là dấu thời gian tuyệt đối, sử dụng cùng tham chiếu thời gian như
loop.time().Added in version 3.7.
Đối tượng máy chủ¶
Các đối tượng máy chủ được tạo bởi các hàm loop.create_server(), loop.create_unix_server(), start_server() và start_unix_server().
Không khởi tạo trực tiếp lớp Server.
- class asyncio.Server¶
Đối tượng Server là trình quản lý bối cảnh không đồng bộ. Khi được sử dụng trong câu lệnh
async with, nó đảm bảo rằng đối tượng Máy chủ bị đóng và không chấp nhận các kết nối mới khi câu lệnhasync withđược hoàn thành:srv = đang chờ loop.create_server(...) không đồng bộ với srv: mã # some # At thời điểm này, srv đã bị đóng và không còn chấp nhận kết nối mới.
Thay đổi trong phiên bản 3.7: Đối tượng máy chủ là trình quản lý bối cảnh không đồng bộ kể từ Python 3.7.
Thay đổi trong phiên bản 3.11: Lớp này được hiển thị công khai dưới dạng
asyncio.Servertrong Python 3.9.11, 3.10.3 và 3.11.- close()¶
Dừng cung cấp: đóng ổ cắm nghe và đặt thuộc tính
socketsthànhNone.Các ổ cắm đại diện cho các kết nối máy khách đến hiện có vẫn còn mở.
Máy chủ bị đóng không đồng bộ; sử dụng coroutine
wait_closed()để đợi cho đến khi máy chủ đóng (và không còn kết nối nào hoạt động nữa).
- close_clients()¶
Đóng tất cả các kết nối máy khách đến hiện có.
Gọi
close()trên tất cả các phương tiện giao thông liên quan.close()nên được gọi trướcclose_clients()khi đóng máy chủ để tránh chạy đua với các máy khách mới kết nối.Added in version 3.13.
- abort_clients()¶
Đóng tất cả các kết nối máy khách đang đến hiện có ngay lập tức mà không cần đợi các hoạt động đang chờ xử lý hoàn tất.
Gọi
abort()trên tất cả các phương tiện giao thông liên quan.close()nên được gọi trướcabort_clients()khi đóng máy chủ để tránh chạy đua với các máy khách mới kết nối.Added in version 3.13.
- get_loop()¶
Trả về vòng lặp sự kiện được liên kết với đối tượng máy chủ.
Added in version 3.7.
- async start_serving()¶
Bắt đầu chấp nhận kết nối.
Phương thức này là bình thường nên nó có thể được gọi khi máy chủ đang phục vụ.
Tham số chỉ từ khóa start_serving cho
loop.create_server()vàasyncio.start_server()cho phép tạo một đối tượng Máy chủ không chấp nhận kết nối ban đầu. Trong trường hợp này,Server.start_serving()hoặcServer.serve_forever()có thể được sử dụng để khiến Máy chủ bắt đầu chấp nhận kết nối.Added in version 3.7.
- async serve_forever()¶
Bắt đầu chấp nhận kết nối cho đến khi coroutine bị hủy. Việc hủy tác vụ
serve_foreverkhiến máy chủ bị đóng.Phương thức này có thể được gọi nếu máy chủ đã chấp nhận kết nối. Chỉ có thể tồn tại một tác vụ
serve_forevertrên một đối tượng Server.Ví dụ:
async def client_connected(reader, writer): # Communicate với khách hàng với luồng # reader/nhà văn. Ví dụ: đang chờ reader.readline() async def main (máy chủ, cổng): srv = đang chờ asyncio.start_server( client_connected, máy chủ, cổng) đang chờ srv.serve_forever() asyncio.run(chính('127.0.0.1', 0))
Added in version 3.7.
- is_serving()¶
Trả về
Truenếu máy chủ chấp nhận kết nối mới.Added in version 3.7.
- async wait_closed()¶
Đợi cho đến khi phương thức
close()hoàn tất và tất cả các kết nối đang hoạt động đã kết thúc.
- sockets¶
Danh sách các đối tượng giống ổ cắm,
asyncio.trsock.TransportSocketmà máy chủ đang lắng nghe.Thay đổi trong phiên bản 3.7: Trước Python 3.7
Server.socketsđược sử dụng để trả về trực tiếp danh sách nội bộ của ổ cắm máy chủ. Trong 3.7 một bản sao của danh sách đó được trả về.
Triển khai vòng lặp sự kiện¶
asyncio có hai cách triển khai vòng lặp sự kiện khác nhau: SelectorEventLoop và ProactorEventLoop.
Theo mặc định, asyncio được định cấu hình để sử dụng EventLoop.
- class asyncio.SelectorEventLoop¶
Một lớp con của
AbstractEventLoopdựa trên mô-đunselectors.Sử dụng selector hiệu quả nhất hiện có cho nền tảng nhất định. Cũng có thể định cấu hình thủ công việc triển khai bộ chọn chính xác sẽ được sử dụng
nhập asyncio bộ chọn nhập async def main(): ... loop_factory = lambda: asyncio.SelectorEventLoop(selectors.SelectSelector()) asyncio.run(main(), loop_factory=loop_factory)
sẵn có: Unix, Windows.
- class asyncio.ProactorEventLoop¶
Một lớp con của
AbstractEventLoopdành cho Windows sử dụng "Cổng hoàn thành I/O" (IOCP).sẵn có: Windows.
- class asyncio.EventLoop¶
Bí danh của lớp con
AbstractEventLoophiệu quả nhất hiện có cho nền tảng nhất định.Nó là bí danh của
SelectorEventLooptrên Unix vàProactorEventLooptrên Windows.Added in version 3.13.
- class asyncio.AbstractEventLoop¶
Lớp cơ sở trừu tượng cho các vòng lặp sự kiện tuân thủ asyncio.
Phần Phương pháp vòng lặp sự kiện liệt kê tất cả các phương thức mà việc triển khai
AbstractEventLoopthay thế nên được xác định.
Ví dụ¶
Lưu ý rằng tất cả các ví dụ trong phần này purposefully đều hiển thị cách sử dụng API vòng lặp sự kiện cấp thấp, chẳng hạn như loop.run_forever() và loop.call_soon(). Các ứng dụng asyncio hiện đại hiếm khi cần phải viết theo cách này; hãy cân nhắc sử dụng các hàm cấp cao như asyncio.run().
Xin chào thế giới với call_soon()¶
Một ví dụ sử dụng phương thức loop.call_soon() để lên lịch gọi lại. Lệnh gọi lại hiển thị "Hello World" và sau đó dừng vòng lặp sự kiện:
nhập asyncio
def hello_world(vòng lặp):
"""Lệnh gọi lại để in 'Xin chào thế giới' và dừng vòng lặp sự kiện"""
print('Xin chào thế giới')
loop.stop()
vòng lặp = asyncio.new_event_loop()
# Schedule một cuộc gọi tới hello_world()
loop.call_soon(hello_world, vòng lặp)
cuộc gọi # Blocking bị gián đoạn bởi loop.stop()
thử:
loop.run_forever()
cuối cùng:
loop.close()
Xem thêm
Một ví dụ Hello World tương tự được tạo bằng coroutine và hàm run().
Hiển thị ngày hiện tại với call_later()¶
Một ví dụ về lệnh gọi lại hiển thị ngày hiện tại mỗi giây. Lệnh gọi lại sử dụng phương thức loop.call_later() để tự lên lịch lại sau 5 giây, sau đó dừng vòng lặp sự kiện:
nhập asyncio
nhập ngày giờ dưới dạng dt
def display_date(end_time, loop):
in(dt.datetime.now())
if (loop.time() + 1.0) < end_time:
loop.call_later(1, display_date, end_time, loop)
khác:
loop.stop()
vòng lặp = asyncio.new_event_loop()
# Schedule cuộc gọi đầu tiên tới display_date()
end_time = loop.time() + 5.0
loop.call_soon(display_date, end_time, loop)
cuộc gọi # Blocking bị gián đoạn bởi loop.stop()
thử:
loop.run_forever()
cuối cùng:
loop.close()
Xem thêm
Một ví dụ current date tương tự được tạo bằng coroutine và hàm run().
Xem bộ mô tả tệp cho các sự kiện đã đọc¶
Đợi cho đến khi bộ mô tả tệp nhận được một số dữ liệu bằng phương thức loop.add_reader() rồi đóng vòng lặp sự kiện
nhập asyncio
từ cặp ổ cắm nhập khẩu
# Create một cặp mô tả tập tin được kết nối
rsock, wsock = socketpair()
vòng lặp = asyncio.new_event_loop()
trình đọc def():
dữ liệu = rsock.recv(100)
print("Đã nhận:", data.decode())
# We đã xong: hủy đăng ký bộ mô tả tập tin
loop.remove_reader(rsock)
# Stop vòng lặp sự kiện
loop.stop()
# Register mô tả tập tin cho sự kiện đọc
loop.add_reader(rsock, reader)
# Simulate việc tiếp nhận dữ liệu từ mạng
loop.call_soon(wsock.send, 'abc'.encode())
thử:
# Run vòng lặp sự kiện
loop.run_forever()
cuối cùng:
# We đã xong. Đóng socket và vòng lặp sự kiện.
rsock.close()
wsock.close()
loop.close()
Xem thêm
Một example tương tự sử dụng phương thức vận chuyển, giao thức và phương thức
loop.create_connection().Một example tương tự khác sử dụng chức năng và luồng
asyncio.open_connection()cấp cao.
Đặt bộ xử lý tín hiệu cho SIGINT và SIGTERM¶
(Ví dụ signal này chỉ hoạt động trên Unix.)
Đăng ký trình xử lý tín hiệu SIGINT và SIGTERM bằng phương thức loop.add_signal_handler()
nhập asyncio
nhập khẩu funtools
hệ điều hành nhập khẩu
tín hiệu nhập khẩu
def Ask_exit(signname, loop):
print("đã nhận được tín hiệu %s: exit" % signame)
loop.stop()
async def main():
vòng lặp = asyncio.get_running_loop()
cho tên đăng nhập trong {'SIGINT', 'SIGTERM'}:
loop.add_signal_handler(
getattr(tín hiệu, tín hiệu),
functools.partial(ask_exit, signame, loop))
đang chờ asyncio.sleep(3600)
print("Vòng lặp sự kiện chạy trong 1 giờ, nhấn Ctrl+C để ngắt.")
print(f"pid {os.getpid()}: gửi SIGINT hoặc SIGTERM để thoát.")
asyncio.run(chính())