Hướng dẫn executor in python - người thực thi trong python

Tác giả đã chọn Quỹ Cứu trợ Covid-19 để nhận quyên góp như một phần của Chương trình Viết cho Đóng góp.

Nội dung chính ShowShow

  • Giới thiệu
  • Điều kiện tiên quyết
  • Bước 1 - Xác định chức năng để thực thi trong các luồng
  • Bước 2 - Sử dụng ThreadPoolExecutor để thực thi chức năng trong các luồng
  • Bước 3 - Xử lý các ngoại lệ từ các chức năng chạy trong các luồng
  • Bước 4 - So sánh thời gian thực hiện có và không có luồng
  • Sự kết luận

Giới thiệu

Điều kiện tiên quyết

Bước 1 - Xác định chức năng để thực thi trong các luồng

Bước 2 - Sử dụng ThreadPoolExecutor để thực thi chức năng trong các luồng

Bước 3 - Xử lý các ngoại lệ từ các chức năng chạy trong các luồng

Bước 4 - So sánh thời gian thực hiện có và không có luồng

Sự kết luận

Chủ đề Python là một hình thức song song cho phép chương trình của bạn chạy nhiều thủ tục cùng một lúc. Sự song song trong Python cũng có thể đạt được bằng cách sử dụng nhiều quy trình, nhưng các luồng đặc biệt phù hợp để tăng tốc các ứng dụng liên quan đến số lượng I/O đáng kể (đầu vào/đầu ra).

Ví dụ Các hoạt động ràng buộc I/O bao gồm thực hiện các yêu cầu web và đọc dữ liệu từ các tệp. Trái ngược với các hoạt động ràng buộc I/O, các hoạt động ràng buộc CPU (như thực hiện toán học với thư viện tiêu chuẩn Python) sẽ không được hưởng lợi nhiều từ các chủ đề Python. The fact that I/O-bound operations benefit more from threads than CPU-bound operations is caused by an idiosyncrasy in Python called the, global interpreter lock. If you’d like, you can learn more about Python’s global interpreter lock in the official Python documentation.

Điều kiện tiên quyết

Bước 1 - Xác định chức năng để thực thi trong các luồng

Bước 2 - Sử dụng ThreadPoolExecutor để thực thi chức năng trong các luồng

Bước 3 - Xử lý các ngoại lệ từ các chức năng chạy trong các luồng

  • Bước 4 - So sánh thời gian thực hiện có và không có luồng

  • Sự kết luận

  • Chủ đề Python là một hình thức song song cho phép chương trình của bạn chạy nhiều thủ tục cùng một lúc. Sự song song trong Python cũng có thể đạt được bằng cách sử dụng nhiều quy trình, nhưng các luồng đặc biệt phù hợp để tăng tốc các ứng dụng liên quan đến số lượng I/O đáng kể (đầu vào/đầu ra).

    Ví dụ Các hoạt động ràng buộc I/O bao gồm thực hiện các yêu cầu web và đọc dữ liệu từ các tệp. Trái ngược với các hoạt động ràng buộc I/O, các hoạt động ràng buộc CPU (như thực hiện toán học với thư viện tiêu chuẩn Python) sẽ không được hưởng lợi nhiều từ các chủ đề Python.
  1. pip install --user requests==2.23.0

Bước 1 - Xác định chức năng để thực thi trong các luồng

Bước 2 - Sử dụng ThreadPoolExecutor để thực thi chức năng trong các luồng

Bước 3 - Xử lý các ngoại lệ từ các chức năng chạy trong các luồng

Bước 4 - So sánh thời gian thực hiện có và không có luồng

Sự kết luận

wiki_page_function.py

import requests

def get_wiki_page_existence(wiki_page_url, timeout=10):
    response = requests.get(url=wiki_page_url, timeout=timeout)

    page_status = "unknown"
    if response.status_code == 200:
        page_status = "exists"
    elif response.status_code == 404:
        page_status = "does not exist"

    return wiki_page_url + " - " + page_status

Chủ đề Python là một hình thức song song cho phép chương trình của bạn chạy nhiều thủ tục cùng một lúc. Sự song song trong Python cũng có thể đạt được bằng cách sử dụng nhiều quy trình, nhưng các luồng đặc biệt phù hợp để tăng tốc các ứng dụng liên quan đến số lượng I/O đáng kể (đầu vào/đầu ra).

Ví dụ Các hoạt động ràng buộc I/O bao gồm thực hiện các yêu cầu web và đọc dữ liệu từ các tệp. Trái ngược với các hoạt động ràng buộc I/O, các hoạt động ràng buộc CPU (như thực hiện toán học với thư viện tiêu chuẩn Python) sẽ không được hưởng lợi nhiều từ các chủ đề Python.

Python 3 bao gồm tiện ích

  1. nano wiki_page_function.py
5 để thực thi mã trong một luồng.

Trong hướng dẫn này, chúng tôi sẽ sử dụng

  1. nano wiki_page_function.py
5 để thực hiện các yêu cầu mạng một cách nhanh chóng. Chúng tôi sẽ xác định một chức năng phù hợp cho việc gọi trong các luồng, sử dụng
  1. nano wiki_page_function.py
5 để thực thi chức năng đó và xử lý kết quả từ các lần thực thi đó.

wiki_page_function.py

  1. nano wiki_page_function.py
8

Đối với hướng dẫn này, chúng tôi sẽ thực hiện các yêu cầu mạng để kiểm tra sự tồn tại của các trang Wikipedia.

Lưu ý: Thực tế là các hoạt động ràng buộc I/O được hưởng lợi nhiều hơn từ các chủ đề so với các hoạt động ràng buộc CPU là do một idiosyncrasy trong Python gọi là khóa phiên dịch toàn cầu. Nếu bạn thích, bạn có thể tìm hiểu thêm về khóa phiên dịch toàn cầu của Python trong tài liệu Python chính thức. The fact that I/O-bound operations benefit more from threads than CPU-bound operations is caused by an idiosyncrasy in Python called the, global interpreter lock. If you’d like, you can learn more about Python’s global interpreter lock in the official Python documentation.

  1. nano wiki_page_function.py
1

Để tận dụng tối đa hướng dẫn này, nên có một số quen thuộc với lập trình trong Python và môi trường lập trình Python địa phương với

  1. nano wiki_page_function.py
2

  1. nano wiki_page_function.py
8 được cài đặt.

Bạn có thể xem lại các hướng dẫn này để biết thông tin cơ bản cần thiết:

Cách viết mã trong Python 3

Cách cài đặt Python 3 và thiết lập môi trường lập trình cục bộ trên Ubuntu 18.041 là một ví dụ về một chức năng như vậy. In general, it is not safe to share Python objects or state between threads without taking special care to avoid concurrency bugs. When defining a function to execute in a thread, it is best to define a function that performs a single job and does not share or publish state to other threads.

import requests

def get_wiki_page_existence(wiki_page_url, timeout=10):
    response = requests.get(url=wiki_page_url, timeout=timeout)

    page_status = "unknown"
    if response.status_code == 200:
        page_status = "exists"
    elif response.status_code == 404:
        page_status = "does not exist"

    return wiki_page_url + " - " + page_status
1 is an example of such a function.

Bước 2 - Sử dụng ThreadPoolExecutor để thực thi chức năng trong các luồng

Bây giờ chúng tôi có một chức năng rất phù hợp với việc gọi các luồng, chúng tôi có thể sử dụng

  1. nano wiki_page_function.py
5 để thực hiện nhiều lời mời của chức năng đó một cách nhanh chóng.

Hãy để thêm mã được tô sáng sau vào chương trình của bạn trong

  1. nano wiki_page_function.py
85:

wiki_page_function.py

  1. nano wiki_page_function.py
8

Hãy cùng xem cách thức hoạt động của mã này:

    1. nano wiki_page_function.py
    86 được nhập để cho chúng tôi quyền truy cập vào
    1. nano wiki_page_function.py
    5.
  • Một câu lệnh
    1. nano wiki_page_function.py
    88 được sử dụng để tạo phiên bản
    1. nano wiki_page_function.py
    5
    1. nano wiki_page_function.py
    10 sẽ nhanh chóng làm sạch các luồng sau khi hoàn thành.
  • Bốn công việc là
    1. nano wiki_page_function.py
    11 cho
    1. nano wiki_page_function.py
    10: một công việc cho mỗi URL trong danh sách
    1. nano wiki_page_function.py
    13.
  • Mỗi cuộc gọi đến
    1. nano wiki_page_function.py
    14 trả về một ví dụ
    1. nano wiki_page_function.py
    15 được lưu trữ trong danh sách
    1. nano wiki_page_function.py
    16.
  • Hàm
    1. nano wiki_page_function.py
    17 chờ đợi mỗi cuộc gọi
    1. nano wiki_page_function.py
    15
    import requests
    
    def get_wiki_page_existence(wiki_page_url, timeout=10):
        response = requests.get(url=wiki_page_url, timeout=timeout)
    
        page_status = "unknown"
        if response.status_code == 200:
            page_status = "exists"
        elif response.status_code == 404:
            page_status = "does not exist"
    
        return wiki_page_url + " - " + page_status
    
    1 để hoàn thành để chúng tôi có thể in kết quả của nó.

Nếu chúng ta chạy lại chương trình này, với lệnh sau:

  1. nano wiki_page_function.py
1

Chúng tôi sẽ thấy đầu ra như sau:

  1. nano wiki_page_function.py
4

Đầu ra này có ý nghĩa: 3 trong số các URL là các trang Wikipedia hợp lệ và một trong số đó là

  1. nano wiki_page_function.py
20 thì không. Lưu ý rằng đầu ra của bạn có thể được đặt hàng khác với đầu ra này. Hàm
  1. nano wiki_page_function.py
21 trong ví dụ này trả về kết quả ngay khi chúng có sẵn, bất kể thứ tự nào đã được gửi.

Bước 3 - Xử lý các ngoại lệ từ các chức năng chạy trong các luồng

Trong bước trước,

import requests

def get_wiki_page_existence(wiki_page_url, timeout=10):
    response = requests.get(url=wiki_page_url, timeout=timeout)

    page_status = "unknown"
    if response.status_code == 200:
        page_status = "exists"
    elif response.status_code == 404:
        page_status = "does not exist"

    return wiki_page_url + " - " + page_status
1 đã trả lại thành công một giá trị cho tất cả các lời mời của chúng tôi. Trong bước này, chúng tôi sẽ thấy rằng
  1. nano wiki_page_function.py
5 cũng có thể tăng các ngoại lệ được tạo ra trong các yêu cầu chức năng có ren.

Hãy cùng xem xét khối mã ví dụ sau:

wiki_page_function.py

  1. nano wiki_page_function.py
9

Khối mã này gần giống với quy mô chúng tôi đã sử dụng trong bước 2, nhưng nó có hai khác biệt chính:

  • Bây giờ chúng tôi vượt qua
    1. nano wiki_page_function.py
    24 đến
    import requests
    
    def get_wiki_page_existence(wiki_page_url, timeout=10):
        response = requests.get(url=wiki_page_url, timeout=timeout)
    
        page_status = "unknown"
        if response.status_code == 200:
            page_status = "exists"
        elif response.status_code == 404:
            page_status = "does not exist"
    
        return wiki_page_url + " - " + page_status
    
    1. Vì gói
    1. nano wiki_page_function.py
    8 won có thể hoàn thành yêu cầu web của mình với Wikipedia trong
    1. nano wiki_page_function.py
    27 giây, nó sẽ tăng ngoại lệ
    1. nano wiki_page_function.py
    28.
  • Chúng tôi bắt
    1. nano wiki_page_function.py
    28 ngoại lệ được nêu ra bởi
    1. nano wiki_page_function.py
    80 và in ra một chuỗi mỗi lần chúng tôi làm như vậy.

Nếu chúng tôi chạy lại chương trình, chúng tôi sẽ thấy đầu ra sau:

  1. nano wiki_page_function.py
0

Bốn tin nhắn

  1. nano wiki_page_function.py
28 được in một trong bốn
  1. nano wiki_page_function.py
13 của chúng tôi, vì không ai trong số chúng có thể hoàn thành trong
  1. nano wiki_page_function.py
27 giây và mỗi trong số bốn cuộc gọi
import requests

def get_wiki_page_existence(wiki_page_url, timeout=10):
    response = requests.get(url=wiki_page_url, timeout=timeout)

    page_status = "unknown"
    if response.status_code == 200:
        page_status = "exists"
    elif response.status_code == 404:
        page_status = "does not exist"

    return wiki_page_url + " - " + page_status
1 đã tăng ngoại lệ
  1. nano wiki_page_function.py
28.

Bây giờ, bạn đã thấy rằng nếu một cuộc gọi chức năng được gửi tới

  1. nano wiki_page_function.py
5 sẽ tăng một ngoại lệ, thì ngoại lệ đó có thể được nêu ra bình thường bằng cách gọi
  1. nano wiki_page_function.py
87. Gọi
  1. nano wiki_page_function.py
87 trên tất cả các yêu cầu đã gửi của bạn đảm bảo rằng chương trình của bạn đã giành được bất kỳ trường hợp ngoại lệ nào được nêu ra từ chức năng chủ đề của bạn.

Bước 4 - So sánh thời gian thực hiện có và không có luồng

Bây giờ, hãy để xác minh rằng sử dụng

  1. nano wiki_page_function.py
5 thực sự làm cho chương trình của bạn nhanh hơn.

Đầu tiên, hãy để thời gian

import requests

def get_wiki_page_existence(wiki_page_url, timeout=10):
    response = requests.get(url=wiki_page_url, timeout=timeout)

    page_status = "unknown"
    if response.status_code == 200:
        page_status = "exists"
    elif response.status_code == 404:
        page_status = "does not exist"

    return wiki_page_url + " - " + page_status
1 nếu chúng ta chạy nó mà không có chủ đề:

wiki_page_function.py

  1. nano wiki_page_function.py
1

Trong ví dụ mã, chúng tôi gọi chức năng

import requests

def get_wiki_page_existence(wiki_page_url, timeout=10):
    response = requests.get(url=wiki_page_url, timeout=timeout)

    page_status = "unknown"
    if response.status_code == 200:
        page_status = "exists"
    elif response.status_code == 404:
        page_status = "does not exist"

    return wiki_page_url + " - " + page_status
1 của chúng tôi với năm mươi URL trang Wikipedia khác nhau từng cái một. Chúng tôi sử dụng hàm
  1. nano wiki_page_function.py
12 để in ra số giây cần thiết để chạy chương trình của chúng tôi.

Nếu chúng ta chạy lại mã này như trước, chúng ta sẽ thấy đầu ra như sau:

  1. nano wiki_page_function.py
2

Các mục 2 Vang47 trong đầu ra này đã bị bỏ qua cho sự ngắn gọn.

Số giây được in sau

  1. nano wiki_page_function.py
13 sẽ khác khi bạn chạy nó trên máy của bạn, đó là OK OK, bạn chỉ nhận được một số cơ sở để so sánh với một giải pháp sử dụng
  1. nano wiki_page_function.py
5. Trong trường hợp này, đó là
  1. nano wiki_page_function.py
15 giây.

Hãy cùng chạy cùng một URL năm mươi Wikipedia thông qua

import requests

def get_wiki_page_existence(wiki_page_url, timeout=10):
    response = requests.get(url=wiki_page_url, timeout=timeout)

    page_status = "unknown"
    if response.status_code == 200:
        page_status = "exists"
    elif response.status_code == 404:
        page_status = "does not exist"

    return wiki_page_url + " - " + page_status
1, nhưng lần này sử dụng
  1. nano wiki_page_function.py
5:

wiki_page_function.py

  1. nano wiki_page_function.py
3

Mã này là cùng một mã chúng tôi đã tạo trong bước 2, chỉ với việc bổ sung một số câu lệnh in cho chúng tôi thấy số giây cần thiết để thực thi mã của chúng tôi.

Nếu chúng tôi chạy lại chương trình, chúng tôi sẽ thấy như sau:

  1. nano wiki_page_function.py
4

Một lần nữa, số giây được in sau

  1. nano wiki_page_function.py
18 sẽ khác nhau trên máy tính của bạn (cũng như thứ tự đầu ra của bạn).

Bây giờ bạn có thể so sánh thời gian thực hiện để tìm nạp URL trang Wikipedia năm mươi Wikipedia có và không có chủ đề.

Trên máy được sử dụng trong hướng dẫn này, không có luồng mất

  1. nano wiki_page_function.py
15 giây và với các luồng mất
  1. nano wiki_page_function.py
40 giây. Chương trình của chúng tôi chạy nhanh hơn đáng kể với các chủ đề.

Sự kết luận

Trong hướng dẫn này, bạn đã học được cách sử dụng tiện ích

  1. nano wiki_page_function.py
5 trong Python 3 để chạy mã hiệu quả là I/O bị ràng buộc. Bạn đã tạo một chức năng phù hợp với việc gọi trong các luồng, đã học cách truy xuất cả đầu ra và ngoại lệ từ các thực thi luồng của chức năng đó và quan sát thấy hiệu suất tăng thu được bằng cách sử dụng các luồng.

Từ đây bạn có thể tìm hiểu thêm về các chức năng đồng thời khác được cung cấp bởi mô -đun

  1. nano wiki_page_function.py
86.