Hướng dẫn call async function from non async python - gọi hàm không đồng bộ từ python không đồng bộ
Vì vậy, tôi bị khóa vào một trình thông dịch Python 3.6.2 theo ứng dụng máy tính để bàn của tôi. Show
Điều tôi muốn là gọi hàm Async từ phương thức hoặc hàm được đồng bộ hóa. Khi gọi chức năng Python từ ứng dụng máy tính để bàn, nó phải là một hàm bình thường không thể chờ đợi. Từ ứng dụng máy tính để bàn, tôi có thể gửi một danh sách các URL và điều tôi muốn là gửi lại phản hồi từ mỗi URL trong một vấn đề không đồng bộ. Đây là lần thử của tôi, tôi đã đánh dấu cú pháp mà tôi không biết cách bỏ qua.
Tôi đã thử thực hiện những thay đổi này:
Nhưng bây giờ tôi kết thúc với lỗi này: cloudfit-public-docsTrong các phần trước của loạt bài này trên Python Asyncio, tôi đã giới thiệu cho bạn các khái niệm cơ bản, cú pháp cơ bản, một vài tính năng tiên tiến hơn và một số thư viện hữu ích. Trong phần này, tôi dự định đi sâu vào các chi tiết của các giao diện, bạn cũng có thể thấy mình cần sử dụng nếu bạn cần kết hợp mã đồng bộ và không đồng bộ trong cùng một dự án. Đây là điều mà chúng tôi đã bắt gặp nhiều lần trong dự án CloudFit của BBC R & D,, đặc biệt là khi sử dụng các thư viện hiện có chưa hỗ trợ trực tiếp với Asyncio. Một điều bạn có thể làm, và một điều bạn thực sự không nênBạn có thể chạy mã Async trừ khi bạn có một vòng lặp sự kiện để chạy nó (mà không thực hiện một số công việc đặc biệt liên quan đến một đối tượng giả mạo là một vòng lặp sự kiện). Vì vậy, chờ đợi các coroutines không đồng bộ trong một chương trình không có vòng lặp sự kiện đang chạy có nghĩa là bạn cần bắt đầu một vòng lặp sự kiện. May mắn thay, điều này không xuất hiện nhiều. Ngược lại, bạn hoàn toàn có thể gọi mã không phải là ASYNC từ mã async, trên thực tế, nó rất dễ thực hiện. Nhưng nếu một cuộc gọi phương thức/chức năng có thể khối khối (tức là mất nhiều thời gian trước khi nó trở lại) thì bạn thực sự không nên. Vấn đề với điều này có thể được nhìn thấy gọn gàng trong mã sau:
Khi mã này được chạy, đầu ra trông giống như thế này:
Như bạn có thể thấy, quầy đã tạm dừng trong suốt thời gian thực hiện yêu cầu HTTP. Điều này là do cuộc gọi Đương nhiên đây là một vấn đề.
Có một số kỹ thuật bạn có thể sử dụng để giảm thiểu, và trong một số trường hợp hoàn toàn loại bỏ, tuy nhiên, vấn đề này. Người thực thi và đa luồngAsyncio về cơ bản là một công nghệ duy nhất. Mỗi vòng lặp sự kiện chạy trên một luồng duy nhất và ghép kênh thời gian chạy của luồng giữa các tác vụ khác nhau. Đây có thể là một mô hình hoạt động rất hiệu quả khi bạn có một nhiệm vụ ràng buộc IO được thực hiện bằng thư viện IO Asyncio-Aware. Đáng buồn thay, không phải tất cả các nhiệm vụ đều bị ràng buộc và tất cả các thư viện đều hỗ trợ Asyncio. Đây là nơi đa luồng xuất hiện. Chỉ vì vòng lặp sự kiện của bạn chạy trên một luồng và ghép kênh sử dụng của nó không có nghĩa là chương trình của bạn có thể cũng có các luồng khác chạy cùng một lúc. Trên thực tế, nó rất hữu ích khi có sẵn một nhóm các chủ đề để bạn có thể gửi công việc chặn dài cho họ và cho phép những cuộc gọi chặn dài đến mỗi người chiếm một chủ đề của riêng họ trong khi họ chạy. Vì đây là một mẫu hữu ích, nên không có gì ngạc nhiên khi thư viện Asyncio cung cấp một cách dễ dàng để làm điều này, sử dụng phương thức Loop Loop Loop ____ ____10. Do đó:
tạo ra đầu ra như thế này:
Và như bạn có thể thấy lần này, bộ đếm không bị chặn bởi yêu cầu HTTP. Vậy nó hoạt động như thế nào? Phương pháp 0 có hai hoặc nhiều đối số và trả về một tương lai. Đối số đầu tiên có thể được sử dụng để chỉ định nhóm chủ đề hoặc nhóm xử lý để sử dụng để chạy mã, nhưng nếu bạn đặt nó thành 2 thì nó sẽ sử dụng nhóm luồng mặc định thuộc sở hữu của vòng lặp sự kiện và điều này hầu như luôn luôn là bạn muốn gì. Tham số thứ hai là một cuộc gọi đồng bộ sẽ được chạy trong một luồng. Bất kỳ tham số nào được truyền qua cho người được gọi khi nó được gọi.Tương lai được trả lại sẽ được đánh dấu là thực hiện khi Callable có thể gọi được cung cấp đã hoàn tất việc thực hiện trên luồng của nó. Nếu nó trả lại một giá trị sẽ được lưu trữ trong tương lai là kết quả, nếu nó nêu ra một ngoại lệ sẽ được lưu trữ trong tương lai như là ngoại lệ của nó. Điều này có nghĩa là đối với nhiều mục đích, bạn có thể đối xử với tương lai được trả lại bởi 0 rất giống với tương lai được trả lại bởi 4, nhưng với kiến thức rằng các nhiệm vụ được tạo ra với 4 sẽ được ghép nối trên luồng của vòng lặp sự kiện, trong khi các nhiệm vụ được tạo bởi 0 sẽ được chạy Trên một chủ đề khác hoàn toàn, và sẽ bắt đầu thực hiện gần như ngay lập tức.Kết thúc các cuộc gọi chặn để chạy trên các chủ đề khác bằng cách sử dụng 0 có lẽ là cách đơn giản nhất và dễ nhất để sử dụng các thư viện không dành cho việc sử dụng Asyncio khi viết chương trình Asyncio. Chắc chắn có những cạm bẫy tiềm năng (đặc biệt là nếu thư viện cơ bản không được đảm bảo an toàn), nhưng trên toàn bộ mã sẽ sử dụng kỹ thuật này và thậm chí bạn có thể sử dụng nó để tạo ra các giấy gói giống như asyncio xung quanh mã đồng bộ trong một Nhiều hoàn cảnh khác nhau. Nó đặc biệt hữu ích cho mã ràng buộc CPU.Tuy nhiên, có một số kỹ thuật khác mà bạn cũng có thể hưởng lợi từ việc có trong hộp công cụ của mình, mặc dù chúng có khả năng được sử dụng ít thường xuyên hơn.
Còn khóa phiên dịch toàn cầu thì sao?Bạn có thể đã nghe nói về khóa phiên dịch toàn cầu của Python, và làm thế nào nó ngăn Python thực sự chạy mã đa luồng thích hợp theo kiểu song song. Điều này tương tác với 0, nhưng không tệ như lần đầu tiên xuất hiện.Thuốc phiên dịch viên thông dịch viên Python là một loại mutex luôn được giữ bởi bất kỳ chủ đề nào hiện đang diễn giải các hướng dẫn Python trong một quy trình duy nhất. Kết quả là, nó thường không thể có hai luồng Python thực sự chạy mã Python đồng thời, mặc dù chúng có thể chuyển qua lại thường xuyên như giữa các hướng dẫn riêng lẻ. Tuy nhiên, nếu một phương thức Python gọi mã gốc cho một mục đích nào đó thì Gil thường sẽ được phát hành. Do đó, nhiều luồng có thể chạy đồng thời nếu tất cả trừ một trong số chúng hiện đang chạy mã gốc. Mã gốc thực hiện chặn IO trong Python phát hành GIL trong thời gian chặn của nó; Điều này có nghĩa là các tác vụ gắn IO bằng cách sử dụng chặn IO không khóa các luồng python khác trong khi chúng chặn. Đối với các nhiệm vụ ràng buộc CPU, điều này có thể là một vấn đề nhiều hơn. Nhiều thư viện để thực hiện các hoạt động ràng buộc CPU gọi mã gốc để thực hiện xử lý nặng của chúng và phát hành GIL để các luồng khác sẽ không bị chặn. Tuy nhiên, nếu bạn cần chạy một tác vụ ràng buộc CPU được viết bằng Python thuần túy trong nền trong khi mã khác của bạn đang chạy thì các vấn đề có thể phát sinh. Các nhiệm vụ trong các luồng khác sẽ chạy chậm hơn, trải qua các tạm dừng thường xuyên khi trình thông dịch chuyển qua lại giữa các luồng. Để làm việc xung quanh điều này, bạn có thể xây dựng một đối tượng của lớp 0 và chuyển nó dưới dạng tham số đầu tiên của ____10, thay vì 2. Điều này sẽ khiến mã của bạn được chạy không phải trong một chủ đề khác, mà trong một quá trình khác hoàn toàn, và do đó Gil sẽ không được chia sẻ.Đi theo một cách khác với Python Exception |