Как запустить несколько функций одновременно в Python?

Как запустить несколько функций одновременно в Python?

Введение

Многопоточность и параллелизм в Python предоставляют возможности для значительного повышения производительности программ за счет одновременного выполнения нескольких задач. Особенно актуальными эти техники становятся в контексте обработки больших объемов данных или при разработке высоконагруженных веб-приложений. Понимание того, как запустить несколько функций одновременно, не только помогает значительно сэкономить время, но и делает код более эффективным и отзывчивым.

Цели данной статьи:

  • Понять, что такое многопоточность и асинхронность.
  • Изучить различные подходы для одновременного запуска функций в Python.

Основы многопоточности

Что такое многопоточность?

Многопоточность позволяет выполнять несколько потоков, или «нитей», в рамках одного процесса одновременно. В Python за это отвечает модуль threading. Многопоточность часто используется для ввода-вывода операций, где процессоры простаивают, ожидая окончания операций.

import threading

def function_1():
    pass

def function_2():
    pass

thread1 = threading.Thread(target=function_1)
thread2 = threading.Thread(target=function_2)

thread1.start()
thread2.start()
thread1.join()
thread2.join()

Проблемы с GIL

Одна из основных проблем, с которыми сталкиваются разработчики при использовании многопоточности в Python, заключается в глобальной блокировке интерпретатора (GIL — Global Interpreter Lock). Она предназначена для упрощения реализации Python-интерпретатора, но создает ограничения при выполнении вычислительно сложных задач в многопоточных приложениях.

import threading
import time

def task():
    time.sleep(1)

threads = [threading.Thread(target=task) for _ in range(5)]
for thread in threads:
    thread.start()
for thread in threads:
    thread.join()
Реклама

Асинхронное программирование

Основы async и await

Асинхронное программирование в Python дает возможность запускать задачи в неблокирующем режиме, обеспечивая более высокую производительность. С помощью ключевых слов async и await, Python позволяет легко создавать и управлять асинхронными функциями.

import asyncio

async def function_1():
    await asyncio.sleep(1)

async def function_2():
    await asyncio.sleep(1)

async def main():
    await asyncio.gather(function_1(), function_2())

asyncio.run(main())

Использование библиотеки concurrent.futures

ThreadPoolExecutor

ThreadPoolExecutor из библиотеки concurrent.futures позволяет удобно управлять пулом потоков, распределяя задачи между ними. Это идеально подходит для ввода-вывода операций.

from concurrent.futures import ThreadPoolExecutor

def function_1():
    pass

def function_2():
    pass

with ThreadPoolExecutor() as executor:
    executor.submit(function_1)
    executor.submit(function_2)

ProcessPoolExecutor

При необходимости выполнять вычислительно сложные задачи, лучше использовать ProcessPoolExecutor, который запускает функции в отдельных процессах, обходя ограничения GIL.

from concurrent.futures import ProcessPoolExecutor

def function_1():
    pass

def function_2():
    pass

with ProcessPoolExecutor() as executor:
    executor.submit(function_1)
    executor.submit(function_2)

Практические примеры

Практическим примером применения параллелизма может быть обработка больших объемов данных. Рассмотрим пример с использованием библиотеки pandas и ProcessPoolExecutor.

import pandas as pd
import numpy as np
from concurrent.futures import ProcessPoolExecutor

def process_data(chunk: pd.DataFrame) -> pd.Series:
    return chunk.sum()

def main():
    data = pd.DataFrame({'a': range(1000000)})
    chunks = np.array_split(data, 10)
    with ProcessPoolExecutor() as executor:
        results = executor.map(process_data, chunks)
    total = sum(results)
    print(total)

if __name__ == '__main__':
    main()

Заключение

Мы рассмотрели различные методы, позволяющие запускать несколько функций одновременно в Python. Многопоточность полезна для ввода-вывода операций, асинхронность позволяет эффективно управлять асинхронными задачами, а concurrent.futures обеспечивает простоту управления потоками и процессами. Каждому подходу есть свое место и время для применения; выбор зависит от специфики задачи и потребностей проекта.

Ссылки


Добавить комментарий