Чистый API для выполнения вызова функции в python - PullRequest
5 голосов
/ 01 марта 2020

Я хотел бы вызвать функцию в потоке. Вызов его с помощью обычного API выглядит следующим образом:

from threading import Thread
import numpy as np
a = np.random.rand(int(1e8),1)

Thread(target=np.savez_compressed, args=('/tmp/values.a', dict(a=a))).start()

Мне было интересно, если бы Pythoni c имел возможность сделать этот многопоточный вызов с более чистым API, без определения функции, которая задает c для np.savez_compressed.

Например, что-то в стиле (псевдокода):

@make_threaded
np.savez_compressed('/tmp/values.a', dict(a=a))

К сожалению, декораторы могут применяться только к определениям функций, поэтому приведенный выше псевдокод недопустим.

РЕДАКТИРОВАТЬ : Я специально не ищу API-интерфейс декоратора. Скорее, более чистый способ сделать вызов функции многопоточным

Ответы [ 2 ]

4 голосов
/ 01 марта 2020

Модуль concurrent.futures предоставляет более высокоуровневый API для использования потоков или процессов для отдельных операций.

from concurrent.futures import ThreadPoolExecutor

executor = ThreadPoolExecutor()
executor.submit(np.savez_compressed, '/tmp/values.a', dict(a=a))

Если вам не нужен весь API Executor, Вы можете определить свой собственный помощник для запуска функции в потоке.

def threaded(call, *args, **kwargs):
    """Execute ``call(*args, **kwargs)`` in a thread"""
    thread = threading.Thread(target=call, args=args, kwargs=kwargs)
    thread.start()
    return thread

threaded(np.savez_compressed, '/tmp/values.a', dict(a=a))
0 голосов
/ 02 марта 2020

OP здесь:

Другое решение, которое я нашел, было использование декораторов с API-интерфейсом "classi c":

from threading import Thread

call_threaded(np.savez_compressed)('/tmp/values.a', dict(a=a))

# https://stackoverflow.com/a/19846691/2476373
def call_threaded(fn):        
    def wrapper(*args, **kwargs):
        thread = Thread(target=fn, args=args, kwargs=kwargs)
        thread.start()
        return thread
    return wrapper
...