Как запускать код параллельно с ThreadPoolExecutor?

#python #python-multithreading

#python #python-многопоточность

Вопрос:

Привет, я действительно новичок в обработке потоков, и это приводит меня в замешательство, как я могу запустить этот код параллельно?

 def search_posts(page):

    page_url = f'https://jsonplaceholder.typicode.com/posts/{page}'
    req = requests.get(page_url)
    res = req.json()
    
    title = res['title']
    
    return title



page = 1

while True:

    with ThreadPoolExecutor() as executer:
        t = executer.submit(search_posts, page)

        title = t.result()

        print(title)

    if page == 20:
        break

    page  = 1
  

Еще один вопрос: нужно ли мне изучать операционные системы, чтобы понять, как работает потоковая передача?

Комментарии:

1. Большое спасибо за продолжение, конечно, я обязательно проверю это

Ответ №1:

Проблема здесь в том, что вы создаете новый ThreadPoolExecutor для каждой страницы. Чтобы выполнять что-то параллельно, создайте только один ThreadPoolExecutor и используйте его map метод:

 import concurrent.futures as cf
import requests


def search_posts(page):
    page_url = f'https://jsonplaceholder.typicode.com/posts/{page}'
    res = requests.get(page_url).json()
    return res['title']


if __name__ == '__main__':
    with cf.ThreadPoolExecutor() as ex: 
        results = ex.map(search_posts, range(1, 21))
    for r in results:
        print(r)
  

Обратите внимание, что использование if __name__ == '__main__' оболочки является хорошей привычкой для повышения переносимости вашего кода.


При использовании потоков следует помнить одну вещь; Если вы используете CPython (реализацию Python из python.org , которая является наиболее распространенной), потоки фактически не выполняются параллельно.

Чтобы упростить управление памятью, только один поток одновременно может выполнять байт-код Python в CPython. Это обеспечивается глобальной блокировкой интерпретатора («GIL») в CPython.

Хорошей новостью является то, что использование requests для получения веб-страницы будет тратить большую часть своего времени на сетевой ввод-вывод. И вообще, GIL освобождается во время ввода-вывода.

Но если вы выполняете вычисления в своих рабочих функциях (т. Е. выполняете байт-код Python), вам следует использовать ProcessPoolExecutor вместо этого.

Если вы используете ProcessPoolExecutor и работаете в ms-Windows, то использование if __name__ == '__main__' оболочки обязательно, потому что в этом случае Python должен быть способен работать с import вашей основной программой без побочных эффектов.