упрощение потоков в Python - PullRequest
1 голос
/ 26 июня 2010

Я ищу способ облегчить мой многопоточный код.

В моем коде много мест, где я делаю что-то вроде:

for arg in array:
   t=Thread(lambda:myFunction(arg))
   t.start()

Т.е. запуск одной и той же функции, каждый раз для разных параметров, в потоках.

Это, конечно, упрощенная версия реального кода, и обычно код внутри цикла for имеет длину ~ 10-20 строк, что нельзя сделать простым, если использовать одну вспомогательную функцию, например myFunction в примере выше (если бы это было так, я мог бы просто использовать пул потоков).

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

for arg in array:
      with threaded():
          myFunction(arg)

т.е. каким-то образом threaded() берет каждую строку кода внутри нее и запускает ее в отдельном потоке.

Я знаю, что контекстные менеджеры не должны использоваться в таких ситуациях, что это, вероятно, плохая идея и потребует безобразного взлома, но тем не менее - можно ли это сделать и как?

Ответы [ 4 ]

1 голос
/ 26 июня 2010

Как насчет этого:

for arg in array:
    def _thread():
        # code here
        print arg

    t = Thread(_thread)
    t.start()

Кроме того, с помощью декораторов вы можете немного подсластить:

0 голосов
/ 26 июня 2010

То, что вы хотите, является своего рода «контекстным пулом потоков».

Взгляните на класс ThreadPool в этом модуле , предназначенный для использования аналогично тому, как вы указали Использование будет примерно таким:

with ThreadPool() as pool:
    for arg in array:
        pool.add_thread(target=myFunction, args=[arg])

Сбои в любой задаче, заданной для ThreadPool, помечают ошибку и выполняют стандартную обработку возврата ошибок.

0 голосов
/ 26 июня 2010

Я думаю, вы слишком усложняете это.Это «шаблон», который я использую:

# util.py
def start_thread(func, *args):
    thread = threading.Thread(target=func, args=args)
    thread.setDaemon(True)
    thread.start()
    return thread

# in another module
import util
...
for arg in array:
    util.start_thread(myFunction, arg)

Я не вижу особой необходимости создавать myFunction.Вы даже можете определить функцию, встроенную в функцию, которая ее запускает.

def do_stuff():
    def thread_main(arg):
        print "I'm a new thread with arg=%s" % arg
    for arg in array:
        util.start_thread(thread_main, arg)

Если вы создаете большое количество потоков, пул потоков определенно имеет больше смысла.Вы можете легко сделать свой собственный с модулями Queue и threading.В основном создайте очередь jobs, создайте рабочие потоки N, дайте каждому потоку "указатель" на очередь и попросите их извлечь задания из очереди и обработать их.

0 голосов
/ 26 июня 2010

Поможет ли вам здесь пул потоков? Существует множество реализаций для Python, например эта .


P.S: все еще интересно узнать, каков ваш точный вариант использования

...