Python không đồng bộ khi nào?
Là một nhà phát triển cốt lõi của Python đã khiến tôi muốn hiểu cách thức hoạt động của ngôn ngữ này. Tôi nhận ra rằng sẽ luôn có những góc khuất mà tôi không biết mọi chi tiết phức tạp, nhưng để có thể trợ giúp về các vấn đề và thiết kế chung của Python, tôi cảm thấy mình nên thử và hiểu ngữ nghĩa cốt lõi của nó cũng như cách mọi thứ hoạt động bên trong. Show Nhưng cho đến gần đây tôi không hiểu cách thức hoạt động của 3/ 4 trong Python 3. 5. Tôi biết rằng 5 trong Python 3. 3 kết hợp với 6 trong Python 3. 4 đã dẫn đến cú pháp mới này. Nhưng việc không thực hiện nhiều công việc liên quan đến mạng -- thứ mà 6 không giới hạn mà còn tập trung vào -- đã khiến tôi không thực sự chú ý nhiều đến tất cả những thứ 3/ 4 này. ý tôi là tôi biết điều đó
là (về cơ bản) tương đương với
Và tôi biết rằng 6 là một khung vòng lặp sự kiện cho phép lập trình không đồng bộ và tôi biết những từ đó (về cơ bản) có nghĩa là gì. Nhưng chưa bao giờ đi sâu vào cú pháp 3/ 4 để hiểu tất cả những thứ này kết hợp với nhau như thế nào, tôi cảm thấy mình không hiểu lập trình bất đồng bộ trong Python, điều này làm tôi khó chịu. Vì vậy, tôi quyết định dành thời gian và thử tìm hiểu xem tất cả những thứ đó hoạt động như thế nào. Và vì tôi đã nghe từ nhiều người rằng họ cũng không hiểu cách thức hoạt động của thế giới lập trình không đồng bộ mới này, nên tôi quyết định viết bài luận này (vâng, bài đăng này đã mất rất nhiều thời gian và dài đến nỗi vợ tôi Bây giờ vì tôi muốn hiểu đúng về cách thức hoạt động của cú pháp, bài tiểu luận này có một số chi tiết kỹ thuật cấp thấp về cách CPython thực hiện mọi việc. Hoàn toàn ổn nếu nó chi tiết hơn bạn muốn hoặc bạn không hiểu hết về nó vì tôi không giải thích mọi sắc thái của nội bộ CPython để giữ cho điều này không biến thành một cuốn sách (e. g. , nếu bạn không biết rằng các đối tượng mã có cờ, mặc kệ đối tượng mã là gì, cũng không sao và bạn không cần quan tâm để lấy thứ gì từ tiểu luận này). Tôi đã cố gắng cung cấp một bản tóm tắt dễ tiếp cận hơn ở cuối mỗi phần để bạn có thể lướt qua các chi tiết nếu chúng trở nên nhiều hơn những gì bạn muốn giải quyết. Một bài học lịch sử về coroutines trong PythonTheo Wikipedia, "Coroutines là các thành phần chương trình máy tính tổng quát hóa các chương trình con cho đa nhiệm không ưu tiên, bằng cách cho phép nhiều điểm vào để tạm dừng và tiếp tục thực thi tại các vị trí nhất định". Đó là một cách nói khá kỹ thuật, "các coroutines là các chức năng mà bạn có thể tạm dừng thực thi". Và nếu bạn đang nói với chính mình, "nghe giống như máy phát điện", bạn sẽ đúng Quay lại Python 2. 2, các trình tạo được giới thiệu lần đầu tiên bởi PEP 255 (chúng còn được gọi là trình lặp trình tạo vì trình tạo triển khai giao thức trình lặp). Lấy cảm hứng chủ yếu từ ngôn ngữ lập trình Biểu tượng, các trình tạo cho phép tạo một trình vòng lặp không lãng phí bộ nhớ khi tính toán giá trị tiếp theo trong phép lặp theo cách đơn giản (bạn luôn có thể tạo một lớp triển khai 23 và 24 mà . Ví dụ: nếu bạn muốn tạo phiên bản 25 của riêng mình, bạn có thể thực hiện điều đó một cách háo hức bằng cách tạo một danh sách các số nguyên 2Tuy nhiên, vấn đề với điều này là nếu bạn muốn một dãy lớn như các số nguyên từ 0 đến 1.000.000, bạn phải tạo một danh sách đủ dài để chứa 1.000.000 số nguyên. Nhưng khi các trình tạo được thêm vào ngôn ngữ, bạn có thể đột nhiên tạo một trình vòng lặp mà không cần phải tạo toàn bộ chuỗi mà không tốn nhiều công sức. Thay vào đó, tất cả những gì bạn phải làm là có đủ bộ nhớ cho một số nguyên tại một thời điểm 6Có một chức năng tạm dừng những gì nó đang làm bất cứ khi nào nó chạm vào biểu thức 26 - mặc dù đó là một câu lệnh cho đến Python 2. 5 -- và sau đó có thể tiếp tục sau đó rất hữu ích về mặt sử dụng ít bộ nhớ hơn, cho phép ý tưởng về các chuỗi vô hạn, v.v.Nhưng như bạn có thể nhận thấy, tất cả các trình tạo đều liên quan đến trình vòng lặp. Bây giờ có một cách tốt hơn để tạo các trình vòng lặp rõ ràng là tuyệt vời (và điều này được thể hiện khi bạn xác định một phương thức 23 trên một đối tượng làm trình tạo), nhưng mọi người biết rằng nếu chúng ta lấy phần "tạm dừng" của trình tạo và thêm vào phần "gửi . Và tính năng chính xác của việc gửi nội dung vào trình tạo bị tạm dừng đã được thêm vào Python 2. 5 cảm ơn PEP 342. Trong số những thứ khác, PEP 342 đã giới thiệu phương pháp 28 trên máy phát điện. Điều này cho phép một người không chỉ tạm dừng trình tạo mà còn gửi giá trị trở lại trình tạo nơi nó tạm dừng. Tiếp tục lấy ví dụ về 25 của chúng ta, bạn có thể làm cho chuỗi nhảy tiến hoặc lùi một lượng nào đó 1Máy phát điện không bị lẫn lộn nữa cho đến Python 3. 3 khi PEP 380 được thêm vào 5. Nói một cách chính xác, tính năng này trao quyền cho bạn tái cấu trúc các trình tạo một cách rõ ràng bằng cách giúp dễ dàng tạo ra mọi giá trị từ một trình vòng lặp (điều mà một trình tạo thuận tiện xảy ra) 3Nhờ làm cho việc tái cấu trúc trở nên dễ dàng hơn, 5 cũng cho phép bạn xâu chuỗi các trình tạo lại với nhau để các giá trị nổi lên và xuống trong ngăn xếp cuộc gọi mà không cần mã phải làm bất kỳ điều gì đặc biệt 5Bản tóm tắtTrình tạo trong Python 2. 2 tạm dừng thực thi mã. Sau khi khả năng gửi giá trị trở lại trình tạo bị tạm dừng đã được giới thiệu trong Python 2. 5, khái niệm về coroutines trong Python đã trở nên khả thi. Và việc bổ sung 5 trong Python 3. 3 giúp tái cấu trúc các trình tạo cũng như xâu chuỗi chúng lại với nhau dễ dàng hơnVòng lặp sự kiện là gì?Điều quan trọng là phải hiểu vòng lặp sự kiện là gì và cách chúng có thể lập trình không đồng bộ nếu bạn quan tâm đến 3/ 4. Nếu bạn đã từng lập trình GUI trước đây -- bao gồm cả công việc giao diện người dùng web -- thì bạn đã từng làm việc với một vòng lặp sự kiện. Nhưng vì khái niệm lập trình không đồng bộ như một cấu trúc ngôn ngữ là mới trong Python, sẽ không sao nếu bạn không biết vòng lặp sự kiện là gìQuay trở lại Wikipedia, vòng lặp sự kiện "là một cấu trúc lập trình chờ đợi và gửi các sự kiện hoặc thông báo trong một chương trình". Về cơ bản, một vòng lặp sự kiện cho phép bạn thực hiện, "khi A xảy ra, hãy làm B". Có lẽ ví dụ đơn giản nhất để giải thích điều này là vòng lặp sự kiện JavaScript có trong mọi trình duyệt. Bất cứ khi nào bạn nhấp vào thứ gì đó ("khi A xảy ra"), lần nhấp đó sẽ được đưa vào vòng lặp sự kiện JavaScript để kiểm tra xem có bất kỳ cuộc gọi lại 65 nào được đăng ký để xử lý lần nhấp đó ("do B"). Nếu bất kỳ cuộc gọi lại nào đã được đăng ký thì cuộc gọi lại được gọi với các chi tiết về lần nhấp. Vòng lặp sự kiện được coi là một vòng lặp vì nó liên tục thu thập các sự kiện và lặp lại chúng để tìm xem phải làm gì với sự kiệnTrong trường hợp của Python, 6 đã được thêm vào thư viện chuẩn để cung cấp vòng lặp sự kiện. Có một trọng tâm về kết nối mạng trong 6, trong trường hợp của vòng lặp sự kiện là biến "khi A xảy ra" thành khi I/O từ ổ cắm sẵn sàng để đọc và/hoặc ghi (thông qua mô-đun 68). Khác với GUI và I/O, các vòng lặp sự kiện cũng thường được sử dụng để thực thi mã trong một luồng hoặc quy trình con khác và để vòng lặp sự kiện đóng vai trò là bộ lập lịch (i. e. , đa nhiệm hợp tác). Nếu bạn tình cờ hiểu GIL của Python, các vòng lặp sự kiện sẽ hữu ích trong trường hợp việc phát hành GIL là có thể và hữu íchBản tóm tắtCác vòng lặp sự kiện cung cấp một vòng lặp cho phép bạn nói, "khi A xảy ra thì hãy làm B". Về cơ bản, một vòng lặp sự kiện sẽ đề phòng khi có điều gì đó xảy ra và khi điều gì đó mà vòng lặp sự kiện quan tâm xảy ra thì nó sẽ gọi bất kỳ mã nào quan tâm đến điều gì đã xảy ra. Python đã đạt được một vòng lặp sự kiện trong thư viện chuẩn ở dạng 6 trong Python 3. 4Cách thức hoạt động của 3 và 4Nó giống như trong Python 3. 4Giữa các trình tạo được tìm thấy trong Python 3. 3 và một vòng lặp sự kiện ở dạng 6, Python 3. 4 đã đủ để hỗ trợ lập trình không đồng bộ ở dạng lập trình đồng thời. Lập trình không đồng bộ về cơ bản là lập trình mà thứ tự thực hiện không được biết trước (do đó không đồng bộ thay vì đồng bộ). Lập trình đồng thời là viết mã để thực thi độc lập với các phần khác, ngay cả khi tất cả thực thi trong một luồng (đồng thời không phải là song song). Ví dụ, sau đây là Python 3. 4 để đếm ngược mỗi giây trong hai lệnh gọi hàm đồng thời, không đồng bộ 7Trong Trăn 3. 4, trình trang trí 13 được sử dụng để gắn nhãn cho một chức năng hoạt động như một quy trình đăng quang được sử dụng với 6 và vòng lặp sự kiện của nó. Điều này đã mang lại cho Python định nghĩa cụ thể đầu tiên về coroutine. một đối tượng đã triển khai các phương thức được thêm vào trình tạo trong PEP 342 và được đại diện bởi lớp cơ sở trừu tượng 15. Điều này có nghĩa là đột nhiên tất cả các trình tạo triển khai giao diện coroutine ngay cả khi chúng không được sử dụng theo kiểu đó. Để khắc phục điều này, 6 yêu cầu tất cả các máy phát điện được sử dụng như một coroutine phải được trang trí bằng 13Với định nghĩa cụ thể về quy trình đăng ký này (phù hợp với API mà trình tạo đã cung cấp), sau đó bạn đã sử dụng 5 trên bất kỳ đối tượng 19 nào để chuyển nó xuống vòng lặp sự kiện, tạm dừng thực thi quy trình đăng ký trong khi bạn chờ đợi điều gì đó xảy ra (là một tương lai . Khi đối tượng tương lai đạt đến vòng lặp sự kiện, nó được theo dõi ở đó cho đến khi đối tượng tương lai hoàn thành bất cứ điều gì nó cần làm. Khi tương lai đã hoàn thành công việc của nó, vòng lặp sự kiện nhận thấy và coroutine bị tạm dừng chờ kết quả của tương lai bắt đầu lại với kết quả của nó được gửi trở lại coroutine bằng phương thức 28 của nóLấy ví dụ của chúng tôi ở trên. Vòng lặp sự kiện bắt đầu từng lệnh gọi quy trình đăng ký 32, thực thi cho đến khi nó chạm vào 5 và hàm 34 ở một trong số chúng. Điều đó trả về một đối tượng 19 được truyền xuống vòng lặp sự kiện và tạm dừng thực thi coroutine. Ở đó, vòng lặp sự kiện theo dõi đối tượng trong tương lai cho đến khi một giây kết thúc (cũng như kiểm tra những thứ khác mà nó đang xem, chẳng hạn như coroutine khác). Sau khi hết một giây, vòng lặp sự kiện lấy quy trình đăng ký 32 bị tạm dừng đã cung cấp cho vòng lặp sự kiện đối tượng tương lai, gửi kết quả của đối tượng tương lai trở lại quy trình đăng ký đã cung cấp cho nó đối tượng tương lai ngay từ đầu và quy trình đăng ký bắt đầu . Điều này tiếp tục cho đến khi tất cả các quy trình đăng ký 32 chạy xong và vòng lặp sự kiện không còn gì để xem. Tôi sẽ thực sự cho bạn thấy một ví dụ hoàn chỉnh về cách hoạt động chính xác của tất cả các công cụ trong vòng lặp sự kiện/quy trình đăng ký này sau, nhưng trước tiên tôi muốn giải thích cách thức hoạt động của 3 và 4Đi từ for x in iterator: yield x 5 đến for x in iterator: yield x 4 trong Python 3. 5Trong Trăn 3. 4, một hàm được gắn cờ là một coroutine cho mục đích lập trình không đồng bộ trông giống như 7Trong Trăn 3. 5, trình trang trí 52 đã được thêm vào để gắn cờ trình tạo là một coroutine giống như 13. Bạn cũng có thể sử dụng 54 để xác định về mặt cú pháp một hàm là một coroutine, mặc dù nó không thể chứa bất kỳ dạng biểu thức 26 nào; 4Tuy nhiên, một điều quan trọng mà 3 và 52 làm là thắt chặt định nghĩa về coroutine là gì. Nó đưa các coroutine từ chỗ chỉ đơn giản là một giao diện thành một loại thực tế, làm cho sự khác biệt giữa bất kỳ trình tạo nào và trình tạo có nghĩa là một coroutine nghiêm ngặt hơn nhiều (và chức năng 70 thậm chí còn chặt chẽ hơn bằng cách nói rằng phải sử dụng 3)Bạn cũng sẽ nhận thấy rằng ngoài 3, Python 3. 5 ví dụ giới thiệu biểu thức 4 (chỉ hợp lệ trong một 54). Trong khi 4 hoạt động giống như 5, các đối tượng được chấp nhận bởi một biểu thức 4 là khác nhau. Các coroutines chắc chắn được cho phép trong một biểu thức 4 vì khái niệm về các coroutines là nền tảng trong tất cả những điều này. Nhưng khi bạn gọi 4 trên một đối tượng, về mặt kỹ thuật, nó cần phải là một đối tượng có thể chờ đợi. một đối tượng định nghĩa một phương thức 70 trả về một trình vòng lặp không phải là một coroutine. Bản thân các coroutine cũng được coi là các đối tượng có thể chờ đợi (do đó tại sao 15 kế thừa từ 72). Định nghĩa này tuân theo truyền thống của Python về việc biến hầu hết các cấu trúc cú pháp thành một lệnh gọi phương thức bên dưới mui xe, giống như 73 là 74 hoặc 75 bên dưới tất cảLàm thế nào để sự khác biệt giữa 5 và 4 diễn ra ở mức độ thấp (i. e. , một máy phát điện với 52 so với. một với 54)? . 5 để có được các chi tiết thực chất. Mã byte cho 40 là 0Mã byte cho 41 là 1Bỏ qua sự khác biệt về số dòng do 40 có trình trang trí 13, sự khác biệt duy nhất có thể nhìn thấy giữa chúng là opcode 44 so với opcode 45. Cả hai chức năng đều được gắn cờ chính xác là coroutines, vì vậy không có sự khác biệt nào ở đó. Trong trường hợp của 44, nó chỉ cần kiểm tra xem đối số của nó là một trình tạo hay coroutine, nếu không, nó gọi 47 trên đối số của nó (việc chấp nhận một đối tượng coroutine bởi opcode cho 5 chỉ được phép khi opcode được sử dụng từ bên trong chính coroutine Nhưng 45 làm điều gì đó khác biệt. Mặc dù mã byte sẽ chấp nhận một coroutine giống như 44, nhưng nó sẽ không chấp nhận một trình tạo nếu chưa được gắn cờ là một coroutine. Tuy nhiên, ngoài các coroutine, mã byte sẽ chấp nhận một đối tượng có thể chờ đợi như đã thảo luận trước đó. Điều này làm cho các biểu thức 5 và biểu thức 4 đều chấp nhận các coroutine trong khi khác nhau về việc chúng có chấp nhận các trình tạo đơn giản hoặc các đối tượng có thể chờ đợi tương ứng hay khôngBạn có thể thắc mắc tại sao sự khác biệt giữa những gì một coroutine dựa trên 3 và một coroutine dựa trên trình tạo sẽ chấp nhận trong các biểu thức tạm dừng tương ứng của chúng? . Vì các trình tạo vốn đã triển khai API cho các coroutine nên sẽ rất dễ vô tình sử dụng một trình tạo trong khi bạn thực sự dự kiến sẽ sử dụng một coroutine. Và vì không phải tất cả các trình tạo đều được viết để sử dụng trong luồng điều khiển dựa trên coroutine, nên bạn cần tránh vô tình sử dụng trình tạo không chính xác. Nhưng vì Python không được biên dịch tĩnh, ngôn ngữ tốt nhất có thể cung cấp là kiểm tra thời gian chạy khi sử dụng quy trình đăng ký do trình tạo xác định. Điều này có nghĩa là khi sử dụng 52, trình biên dịch của Python không thể biết liệu một trình tạo sẽ được sử dụng như một quy trình đăng quang hay chỉ là một trình tạo đơn giản (hãy nhớ rằng chỉ vì cú pháp nói 52 không có nghĩa là ai đó chưa hoàn thành trước đó Một điểm rất quan trọng mà tôi muốn làm rõ về sự khác biệt giữa một coroutine dựa trên trình tạo và một 3 là chỉ những coroutine dựa trên trình tạo mới thực sự có thể tạm dừng thực thi và buộc một thứ gì đó được gửi xuống vòng lặp sự kiện. Bạn thường không thấy chi tiết rất quan trọng này vì bạn thường gọi các hàm dành riêng cho vòng lặp sự kiện như hàm 34 vì các vòng lặp sự kiện triển khai API của riêng chúng và đây là loại hàm phải lo lắng về chi tiết nhỏ này. Đối với đại đa số chúng ta, chúng ta sẽ làm việc với các vòng lặp sự kiện hơn là viết chúng và do đó chỉ viết 3 coroutines và không bao giờ cần thực sự quan tâm đến điều này. Nhưng nếu bạn giống tôi và đang thắc mắc tại sao bạn không thể viết một cái gì đó như 34 chỉ bằng cách sử dụng 3 coroutines, thì đây có thể là "aha. " khoảng khăcBản tóm tắtHãy tóm tắt tất cả những điều này thành các thuật ngữ đơn giản hơn. Xác định một phương thức với 54 làm cho nó trở thành một coroutine. Một cách khác để tạo một coroutine là gắn cờ một trình tạo bằng 52 -- về mặt kỹ thuật, cờ là cờ 00 trên một đối tượng mã -- hoặc một lớp con của 15. Bạn chỉ có thể tạm dừng chuỗi cuộc gọi coroutine với một coroutine dựa trên trình tạoMột đối tượng có thể chờ đợi là một coroutine hoặc một đối tượng xác định 70 -- về mặt kỹ thuật là 72 -- trả về một iterator không phải là một coroutine. Biểu thức 4 về cơ bản là 5 nhưng với các hạn chế chỉ hoạt động với các đối tượng có thể chờ đợi (trình tạo đơn giản sẽ không hoạt động với biểu thức 4). Hàm 3 là một coroutine có các câu lệnh 56 -- bao gồm cả _______025 ẩn ở cuối mỗi hàm trong Python -- và/hoặc các biểu thức 4 (không được phép sử dụng các biểu thức 26). Các hạn chế đối với các hàm 3 là để đảm bảo rằng bạn không vô tình trộn và khớp các coroutine dựa trên trình tạo với các trình tạo khác vì mục đích sử dụng dự kiến của hai loại trình tạo này khá khác nhauHãy nghĩ về 3/ 4 như một API cho lập trình không đồng bộMột điều quan trọng mà tôi muốn chỉ ra thực sự là điều mà tôi đã không thực sự nghĩ sâu về nó cho đến khi tôi xem bài phát biểu quan trọng về Python Brasil 2015 của David Beazley. Trong buổi nói chuyện đó, David đã chỉ ra rằng 3/ 4 thực sự là một API dành cho lập trình không đồng bộ (anh ấy đã nhắc lại với tôi trên Twitter). Ý của David khi nói điều này là mọi người không nên nghĩ rằng 3/ 4 đồng nghĩa với 6, mà thay vào đó hãy nghĩ rằng 6 là một khuôn khổ có thể sử dụng API 3/ 4 cho lập trình không đồng bộDavid thực sự tin rằng ý tưởng về việc 3/ 4 là một API lập trình không đồng bộ mà anh ấy đã tạo dự án 41 để triển khai vòng lặp sự kiện của riêng mình. Điều này đã giúp tôi hiểu rõ rằng 3/ 4 cho phép Python cung cấp các khối xây dựng cho lập trình không đồng bộ, nhưng không ràng buộc bạn vào một vòng lặp sự kiện cụ thể hoặc các chi tiết cấp thấp khác (không giống như các ngôn ngữ lập trình khác tích hợp vòng lặp sự kiện vào . Điều này cho phép các dự án như 41 không chỉ hoạt động khác ở cấp độ thấp hơn (e. g. , 6 sử dụng các đối tượng trong tương lai làm API để giao tiếp với vòng lặp sự kiện của nó trong khi 41 sử dụng các bộ dữ liệu), nhưng cũng có các đặc điểm hiệu suất và tiêu điểm khác nhau (e. g. , 6 có toàn bộ khuôn khổ để triển khai các lớp vận chuyển và giao thức giúp nó có thể mở rộng trong khi 41 đơn giản hơn và mong người dùng lo lắng về loại điều đó nhưng cũng cho phép nó chạy nhanh hơn)Dựa trên lịch sử (ngắn) của lập trình không đồng bộ trong Python, có thể hiểu rằng mọi người có thể nghĩ rằng 3/ 4 == 6. Ý tôi là 6 là thứ đã giúp lập trình không đồng bộ trong Python 3. 4 và là một yếu tố thúc đẩy để thêm 3/ 4 vào Python 3. 5. Nhưng thiết kế của 3/ 4 đủ linh hoạt để không yêu cầu 6 hoặc bóp méo bất kỳ quyết định thiết kế quan trọng nào chỉ dành cho khuôn khổ đó. Nói cách khác, 3/ 4 tiếp tục truyền thống của Python là thiết kế mọi thứ trở nên linh hoạt nhất có thể trong khi vẫn thực dụng để sử dụng (và triển khai)Một ví dụTại thời điểm này, đầu của bạn có thể tràn ngập các thuật ngữ và khái niệm mới, khiến bạn hơi khó nắm bắt đầy đủ cách thức hoạt động của tất cả những điều này để cung cấp cho bạn lập trình không đồng bộ. Để giúp làm cho mọi thứ trở nên cụ thể hơn, đây là một ví dụ lập trình không đồng bộ hoàn chỉnh (nếu giả định), từ đầu đến cuối từ vòng lặp sự kiện và các chức năng được liên kết với mã người dùng. Ví dụ này có các coroutines đại diện cho các lần phóng tên lửa riêng lẻ nhưng dường như đang đếm ngược đồng thời. Đây là lập trình không đồng bộ thông qua đồng thời; 2Như tôi đã nói, nó đã được tạo ra, nhưng nếu bạn chạy cái này trong Python 3. 5, bạn sẽ nhận thấy rằng cả ba coroutine đều chạy độc lập trong một luồng và tổng thời gian chạy là khoảng 5 giây. Bạn có thể coi 60, 61 và 62 là những gì mà nhà cung cấp vòng lặp sự kiện như 6 và 41 sẽ cung cấp cho bạn. Đối với người dùng bình thường, chỉ có mã trong 32 và 66 là quan trọng. Như bạn có thể thấy, không có phép thuật nào đối với 3, 4 hoặc toàn bộ thỏa thuận lập trình không đồng bộ này; Hy vọng và ước mơ của tôi cho tương laiBây giờ tôi đã hiểu cách lập trình không đồng bộ này hoạt động trong Python, tôi muốn sử dụng nó mọi lúc. Đó là một khái niệm tuyệt vời, tốt hơn rất nhiều so với thứ mà bạn đã sử dụng chủ đề trước đây. Vấn đề là Python 3. 5 quá mới nên 3/ 4 cũng rất mới. Điều đó có nghĩa là không có nhiều thư viện hỗ trợ lập trình bất đồng bộ như thế này. Chẳng hạn, để thực hiện các yêu cầu HTTP, bạn phải tự tạo yêu cầu HTTP bằng tay (yuck), hãy sử dụng một dự án như khung 71 để thêm HTTP vào đầu vòng lặp sự kiện khác (trong trường hợp này là 6) hoặc hy vọng có nhiều dự án hơn Cá nhân tôi hy vọng các dự án như 73 sẽ thành công để chúng tôi có sự tách biệt rõ ràng giữa việc lấy dữ liệu nhị phân từ I/O và cách chúng tôi diễn giải dữ liệu nhị phân đó. Loại trừu tượng này rất quan trọng vì hầu hết các thư viện I/O trong Python được liên kết khá chặt chẽ với cách chúng thực hiện I/O và cách chúng xử lý dữ liệu đến từ I/O. Đây là sự cố với gói 76 trong thư viện chuẩn của Python vì gói này không có trình phân tích cú pháp HTTP mà có đối tượng kết nối thực hiện tất cả I/O cho bạn. Và nếu bạn đang hy vọng 77 sẽ hỗ trợ lập trình không đồng bộ, thì hy vọng của bạn đã tiêu tan vì I/O đồng bộ mà 77 sử dụng đã được đưa vào thiết kế của nó. Sự thay đổi về khả năng thực hiện lập trình không đồng bộ này mang lại cho cộng đồng Python cơ hội khắc phục sự cố mà cộng đồng này gặp phải khi không có sự trừu tượng hóa ở các lớp khác nhau của ngăn xếp mạng. Và chúng tôi có lợi thế là không khó để làm cho mã không đồng bộ chạy như thể nó đồng bộ, vì vậy các công cụ lấp đầy khoảng trống cho lập trình không đồng bộ có thể hoạt động ở cả hai thế giớiTôi cũng hy vọng rằng Python sẽ nhận được một số hình thức hỗ trợ trong 3 coroutines cho 26. Có thể điều này sẽ yêu cầu một từ khóa khác (có thể giống như 81?), nhưng thực tế là bạn thực sự không thể triển khai một hệ thống vòng lặp sự kiện chỉ với 3 coroutine làm phiền tôi. May mắn thay, hóa ra tôi không phải là người duy nhất nghĩ điều này, và vì tác giả của PEP 492 cũng đồng ý với tôi, nên tôi nghĩ có cơ hội loại bỏ điều nàySự kết luậnVề cơ bản, 3 và 4 là các trình tạo ưa thích mà chúng tôi gọi là coroutines và có một số hỗ trợ bổ sung cho những thứ được gọi là đối tượng có thể chờ đợi và biến các trình tạo đơn giản thành coroutines. Tất cả những điều này kết hợp với nhau để hỗ trợ đồng thời để chúng tôi hỗ trợ tốt hơn cho lập trình không đồng bộ trong Python. Nó tuyệt vời và dễ sử dụng hơn nhiều so với các cách tiếp cận có thể so sánh được như luồng -- Tôi đã viết một ví dụ từ đầu đến cuối về lập trình không đồng bộ dưới 100 dòng mã Python đã nhận xét -- trong khi vẫn khá linh hoạt và nhanh chóng (Câu hỏi thường gặp về đồ cổ nói rằng nó . ). Tôi rất vui vì điều này đã xuất hiện trong Python 3 và tôi mong cộng đồng đón nhận nó và giúp tăng cường sự hỗ trợ của nó trong các thư viện và khung để tất cả chúng ta đều có thể hưởng lợi từ việc lập trình không đồng bộ trong Python
Python có không đồng bộ không?Async IO là một thiết kế lập trình đồng thời đã nhận được sự hỗ trợ riêng trong Python , phát triển nhanh chóng từ Python 3. 4 đến 3. 7, và có lẽ hơn thế nữa. Bạn có thể đang nghĩ một cách sợ hãi, “Đồng thời, song song, phân luồng, đa xử lý. Đó là rất nhiều để nắm bắt rồi.
Python có đồng bộ hay không đồng bộ không?Có hai loại phương thức cơ bản trong Parallels Python API. đồng bộ và không đồng bộ . Khi một phương thức đồng bộ được gọi, nó sẽ hoàn thành việc thực thi trước khi quay lại trình gọi. Một phương thức không đồng bộ bắt đầu một công việc ở chế độ nền và trả lại cho người gọi ngay lập tức.
Phiên bản Python nào có Asyncio?asyncio yêu cầu Python 3. 3 trở lên . Mô-đun asyncio là một phần của thư viện chuẩn Python kể từ Python 3. 4. asyncio là một phần mềm miễn phí được phân phối theo giấy phép Apache phiên bản 2. 0.
Tại sao chúng tôi sử dụng async trong Python?Mất nhiều thời gian để mở kết nối và đợi người khác hoàn thành công việc của họ. Mặt khác, async cung cấp cho bạn phương thức mở hàng nghìn kết nối cùng lúc và hoán đổi giữa từng kết nối khi chúng kết thúc và trả về kết quả . |