Trì hoãn mã [còn được gọi là ngủ] đúng như tên gọi của nó, việc trì hoãn thực thi mã trong một khoảng thời gian. Nhu cầu trì hoãn mã phổ biến nhất là khi chúng tôi đang đợi một số quy trình khác kết thúc để chúng tôi có thể làm việc với kết quả của quy trình đó. Trong các hệ thống đa luồng, một luồng có thể muốn đợi một luồng khác hoàn thành thao tác để tiếp tục làm việc với kết quả đó
Một ví dụ khác có thể làm giảm bớt căng thẳng cho máy chủ mà chúng tôi đang làm việc cùng. Ví dụ: trong khi quét web [về mặt đạo đức] và tuân theo Điều khoản dịch vụ của trang web được đề cập, tuân theo tệp
14:33:55.282626
14:34:00.287661
9 - bạn rất có thể muốn trì hoãn việc thực hiện từng yêu cầu để không làm quá tải tài nguyên của máy chủNhiều yêu cầu, được thực hiện liên tiếp nhanh chóng, tùy thuộc vào máy chủ được đề cập, có thể nhanh chóng chiếm lấy tất cả các kết nối miễn phí và trở thành một cuộc tấn công DoS một cách hiệu quả. Để có không gian thở, cũng như để đảm bảo rằng chúng tôi không tác động tiêu cực đến người dùng trang web hoặc chính trang web - chúng tôi sẽ giới hạn số lượng yêu cầu được gửi bằng cách trì hoãn từng yêu cầu
Một học sinh đang chờ kết quả kỳ thi có thể tức giận làm mới trang web của trường họ, chờ đợi tin tức. Ngoài ra, họ có thể viết một đoạn script kiểm tra xem trang web có gì mới không. Theo một nghĩa nào đó, độ trễ mã về mặt kỹ thuật có thể trở thành lập lịch mã với điều kiện kết thúc và vòng lặp hợp lệ - giả sử rằng cơ chế độ trễ tại chỗ không bị chặn
Trong bài viết này, chúng ta sẽ xem cách trì hoãn thực thi mã trong Python - còn được gọi là ngủ
Một trong những giải pháp phổ biến nhất cho vấn đề này là chức năng
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
0 của mô-đun print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
1 tích hợp. Nó chấp nhận số giây bạn muốn quy trình ngủ - không giống như nhiều ngôn ngữ khác dựa trên mili giâyimport datetime
import time
print[datetime.datetime.now[].time[]]
time.sleep[5]
print[datetime.datetime.now[].time[]]
Kết quả này trong
14:33:55.282626
14:34:00.287661
Khá rõ ràng, chúng ta có thể thấy độ trễ 5 giây giữa hai câu lệnh
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
2, với độ chính xác khá cao - xuống đến chữ số thập phân thứ hai. Nếu bạn muốn ngủ ít hơn 1 giây, bạn cũng có thể dễ dàng chuyển các số không nguyênprint[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
14:46:16.198404
14:46:16.448840
print[datetime.datetime.now[].time[]]
time.sleep[1.28]
print[datetime.datetime.now[].time[]]
14:46:16.448911
14:46:17.730291
Mặc dù vậy, hãy nhớ rằng với 2 chữ số thập phân, thời lượng ngủ có thể không chính xác, đặc biệt là vì nó khó kiểm tra, do thực tế là các câu lệnh
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
2 cũng mất một khoảng thời gian [có thể thay đổi] để thực thiTuy nhiên, có một nhược điểm lớn đối với chức năng
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
4, rất đáng chú ý trong môi trường đa luồngthời gian. ngủ [] đang chặn
Nó nắm bắt luồng đang bật và chặn luồng đó trong suốt thời gian ngủ. Điều này làm cho nó không phù hợp với thời gian chờ đợi lâu hơn, vì nó làm tắc luồng của bộ xử lý trong khoảng thời gian đó. Ngoài ra, điều này làm cho nó không phù hợp với Ứng dụng không đồng bộ và phản ứng, đôi khi yêu cầu phản hồi và dữ liệu thời gian thực
Một điều khác cần lưu ý về
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
4 là bạn không thể dừng nó lại. Sau khi nó bắt đầu, bạn không thể hủy nó từ bên ngoài mà không chấm dứt toàn bộ chương trình hoặc nếu bạn khiến chính phương thức print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
0 đưa ra một ngoại lệ, điều này sẽ dừng nóLập trình không đồng bộ và phản ứng
Lập trình không đồng bộ xoay quanh việc thực thi song song - trong đó một tác vụ có thể được thực thi và kết thúc độc lập với luồng chính
Trong Lập trình đồng bộ - nếu Chức năng A gọi Chức năng B, nó sẽ dừng thực thi cho đến khi Chức năng B kết thúc thực thi, sau đó Chức năng A có thể tiếp tục
Trong Lập trình không đồng bộ - nếu Hàm A gọi Hàm B, bất kể sự phụ thuộc của nó vào kết quả từ Hàm B, cả hai có thể thực thi cùng một lúc và nếu cần, hãy đợi hàm kia kết thúc để sử dụng kết quả của nhau
Lập trình phản ứng là một tập hợp con của Lập trình không đồng bộ, kích hoạt thực thi mã một cách phản ứng, khi dữ liệu được hiển thị, bất kể chức năng được cho là xử lý nó có đang bận hay không. Lập trình phản ứng phụ thuộc rất nhiều vào Kiến trúc hướng thông báo [trong đó thông báo thường là một sự kiện hoặc lệnh]
Cả ứng dụng Không đồng bộ và Phản ứng đều là những ứng dụng bị chặn mã nhiều - vì vậy sử dụng thứ gì đó như
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
4 không phù hợp với chúng. Chúng ta hãy xem một số tùy chọn trì hoãn mã không chặnTrì hoãn mã với asyncio. ngủ[]
Asyncio là một thư viện Python dành riêng cho việc viết mã đồng thời và sử dụng cú pháp
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
8/print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
9, cú pháp này có thể quen thuộc với các nhà phát triển đã sử dụng nó trong các ngôn ngữ khácHãy cài đặt mô-đun qua
14:46:16.198404
14:46:16.448840
0print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
8Sau khi cài đặt, chúng tôi có thể đưa nó vào tập lệnh của mình và viết lại chức năng của chúng tôi
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
0Khi làm việc với
14:46:16.198404
14:46:16.448840
2, chúng tôi đánh dấu các chức năng chạy không đồng bộ là print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
8 và print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
9 là kết quả của các hoạt động chẳng hạn như 14:46:16.198404
14:46:16.448840
5 sẽ kết thúc vào một thời điểm nào đó trong tương laiTương tự như ví dụ trước, thao tác này sẽ in hai lần, cách nhau 5 giây
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
5Hãy xem hướng dẫn thực hành, thực tế của chúng tôi để học Git, với các phương pháp hay nhất, tiêu chuẩn được ngành chấp nhận và bao gồm bảng gian lận. Dừng các lệnh Git trên Google và thực sự tìm hiểu nó
Mặc dù vậy, điều này không thực sự minh họa lợi ích của việc sử dụng
14:46:16.198404
14:46:16.448840
5. Hãy viết lại ví dụ để chạy song song một số tác vụ, trong đó sự khác biệt này rõ ràng hơn rất nhiềuprint[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
7Ở đây, chúng ta có một hàm
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
8, mô phỏng một tác vụ tốn nhiều công sức mất 5 giây để hoàn thành. Sau đó, sử dụng 14:46:16.198404
14:46:16.448840
2, chúng tôi tạo nhiều tác vụ. Tuy nhiên, mỗi tác vụ có thể chạy không đồng bộ, chỉ khi chúng ta gọi chúng không đồng bộ. Nếu chúng ta chạy chúng tuần tự, chúng cũng sẽ thực thi tuần tựĐể gọi chúng song song, chúng tôi sử dụng hàm
14:46:16.198404
14:46:16.448840
9, tốt, tập hợp các tác vụ và thực thi chúng14:33:55.282626
14:34:00.287661
0Tất cả chúng đều được thực hiện cùng một lúc và thời gian chờ đợi của ba trong số chúng không phải là 15 giây - mà là 5
Mặt khác, nếu chúng tôi chỉnh sửa mã này để sử dụng
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
4 thay thế14:33:55.282626
14:34:00.287661
1Chúng tôi sẽ đợi 5 giây giữa mỗi câu lệnh
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
214:33:55.282626
14:34:00.287661
2Lớp
print[datetime.datetime.now[].time[]]
time.sleep[1.28]
print[datetime.datetime.now[].time[]]
2 là một lớp print[datetime.datetime.now[].time[]]
time.sleep[1.28]
print[datetime.datetime.now[].time[]]
3, chỉ có thể chạy và thực hiện các hoạt động sau một khoảng thời gian nhất định đã trôi qua. Tuy nhiên, hành vi này chính xác là những gì chúng tôi đang tìm kiếm, hơi quá mức cần thiết khi sử dụng các print[datetime.datetime.now[].time[]]
time.sleep[1.28]
print[datetime.datetime.now[].time[]]
3 để trì hoãn mã nếu bạn chưa làm việc với một hệ thống đa luồngLớp
print[datetime.datetime.now[].time[]]
time.sleep[1.28]
print[datetime.datetime.now[].time[]]
2 cần tới print[datetime.datetime.now[].time[]]
time.sleep[1.28]
print[datetime.datetime.now[].time[]]
6 và có thể tạm dừng qua print[datetime.datetime.now[].time[]]
time.sleep[1.28]
print[datetime.datetime.now[].time[]]
7. Hàm tạo của nó chấp nhận một số nguyên, biểu thị số giây phải đợi trước khi thực thi tham số thứ hai - một hàmHãy tạo một hàm và thực thi nó thông qua một
print[datetime.datetime.now[].time[]]
time.sleep[1.28]
print[datetime.datetime.now[].time[]]
214:33:55.282626
14:34:00.287661
3Kết quả này trong
14:33:55.282626
14:34:00.287661
4Phương thức
print[datetime.datetime.now[].time[]]
time.sleep[1.28]
print[datetime.datetime.now[].time[]]
7 thực sự hữu ích nếu chúng ta có nhiều hàm đang chạy và chúng ta muốn hủy thực thi một hàm, dựa trên kết quả của một hàm khác hoặc trên một điều kiện khácHãy viết một hàm
14:46:16.448911
14:46:17.730291
0, gọi cả hai hàm 14:46:16.448911
14:46:17.730291
1 và 14:46:16.448911
14:46:17.730291
2. 14:46:16.448911
14:46:17.730291
1 được gọi là nguyên trạng - và trả về một số nguyên ngẫu nhiên trong khoảng từ 1 đến 10, mô phỏng thời gian cần thiết để chạy hàm đó14:46:16.448911
14:46:17.730291
2 được gọi thông qua một print[datetime.datetime.now[].time[]]
time.sleep[1.28]
print[datetime.datetime.now[].time[]]
2 và nếu kết quả của 14:46:16.448911
14:46:17.730291
1 lớn hơn 14:46:16.448911
14:46:17.730291
7, thì 14:46:16.448911
14:46:17.730291
2 sẽ bị hủy bỏ, ngược lại nếu 14:46:16.448911
14:46:17.730291
1 chạy trong khoảng thời gian "dự kiến" nhỏ hơn 14:46:16.448911
14:46:17.730291
7 - thì 14:46:16.448911
14:46:17.730291
2 sẽ chạy sau khi bộ đếm thời gian kết thúc14:33:55.282626
14:34:00.287661
5Chạy mã này nhiều lần sẽ trông giống như dòng
14:33:55.282626
14:34:00.287661
6Trì hoãn mã với sự kiện
Lớp
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
82 có thể được sử dụng để tạo các sự kiện. Một sự kiện đơn lẻ có thể được "lắng nghe" bởi nhiều chủ đề. Hàm print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
83 chặn luồng đang bật, trừ khi print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
84. Sau khi bạn print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
85 một Sự kiện, tất cả các chủ đề đang chờ sẽ được đánh thức và print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
83 trở thành không bị chặnĐiều này có thể được sử dụng để đồng bộ hóa các luồng - tất cả chúng chồng chất lên nhau và
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
87 cho đến khi một Sự kiện nhất định được đặt, sau đó, chúng có thể ra lệnh cho luồng của chúngHãy tạo một phương thức
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
88 và chạy nó nhiều lần trên các luồng khác nhau. Mỗi người phục vụ bắt đầu làm việc vào một thời điểm nhất định và kiểm tra xem họ có còn đến giờ mỗi giây hay không, ngay trước khi họ gọi món, quá trình này mất một giây để hoàn thành. Họ sẽ làm việc cho đến khi Sự kiện được thiết lập - hay đúng hơn là thời gian làm việc của họ đã hếtMỗi người phục vụ sẽ có luồng riêng của họ, trong khi quản lý nằm trong luồng chính và gọi khi mọi người có thể gọi về nhà. Vì hôm nay họ cảm thấy hào phóng hơn, họ sẽ cắt giảm thời gian làm việc và để những người phục vụ về nhà sau 4 giây làm việc
14:33:55.282626
14:34:00.287661
7Chạy mã này dẫn đến
14:33:55.282626
14:34:00.287661
8Sự kiện
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
89 được sử dụng ở đây để đồng bộ hóa hai luồng và kiểm soát khi nào chúng hoạt động và khi nào không, trì hoãn việc thực thi mã theo thời gian đã đặt giữa các lần kiểm traPhần kết luận
Trong hướng dẫn này, chúng ta đã xem xét một số cách để trì hoãn việc thực thi mã trong Python - mỗi cách áp dụng cho một ngữ cảnh và yêu cầu khác nhau
Phương pháp
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
4 thông thường khá hữu ích cho hầu hết các ứng dụng, tuy nhiên, nó không thực sự tối ưu trong thời gian chờ đợi lâu, không được sử dụng phổ biến để lập lịch trình đơn giản và đang chặnSử dụng
14:46:16.198404
14:46:16.448840
2, chúng tôi có phiên bản không đồng bộ của print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
4 mà chúng tôi có thể print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
9Lớp
print[datetime.datetime.now[].time[]]
time.sleep[1.28]
print[datetime.datetime.now[].time[]]
2 trì hoãn việc thực thi mã và có thể bị hủy nếu cầnLớp
print[datetime.datetime.now[].time[]]
time.sleep[0.25]
print[datetime.datetime.now[].time[]]
82 tạo các sự kiện mà nhiều luồng có thể lắng nghe và phản hồi tương ứng, trì hoãn việc thực thi mã cho đến khi một sự kiện nhất định được đặt