在python中产生一个线程

时间:2010-05-21 13:11:12

标签: python

我有一系列'任务',我想在不同的线程中运行。任务将由单独的模块执行。每个都包含用于处理其任务的业务逻辑。

给定一个任务元组,我希望能够为每个模块生成一个新线程,如下所示。

from foobar import alice, bob charles
data = getWorkData()
# these are enums (which I just found Python doesn't support natively) :(
tasks = (alice, bob, charles)

for task in tasks
  # Ok, just found out Python doesn't have a switch - @#$%!
  # yet another thing I'll need help with then ...
  switch
    case alice:
      #spawn thread here - how ?
      alice.spawnWorker(data)

没有猜测我还在考虑使用C ++的奖品。如何使用Pythonic'enums'和'switch'以Pythonic方式编写它,并能够在新线程中运行模块。

显然,这些模块都有一个派生自一个名为Plugin的ABC(抽象基类)的类。 spawnWorker()方法将在Plugin接口上声明,并在各个模块中实现的类中定义。

也许,有一种更好的(即Pythonic)做这一切的方式?我有兴趣知道

[编辑]

我刚刚阅读了更多的机器人,似乎Python没有真正意义上的线程实现(至少,不是C ++程序员会想到的意义)。在任何情况下,这对我来说都不是一个限制。每个任务都相当耗时,我不想阻止启动一个任务直到另一个任务完成,这就是我使用线程的原因。时间切片并不会让我感到烦恼 - 只要它们几乎同时启动(或者不久之后),Python就可以在它们之间尽可能多地进行时间间隔 - 这对我很好。

我在SO上看到了类似问题的答案。

用户提供了一个简单的线程类,如下所示:

import threading
class Foo (threading.Thread):
    def __init__(self,x):
        self.__x = x
        threading.Thread.__init__(self)
    def run (self):
          print str(self.__x)

for x in xrange(20):
    Foo(x).start()

我正在考虑将此用于我的ABC插件。那么我的问题是我将代码放在实际任务完成的位置(即业务逻辑)。我假设这是在Foo类的run()方法中(我知道明显的问题,但我不想做任何假设)。

我的想法是在正确的轨道上还是有缺陷的(如果有缺陷 - 我错过了什么?)

4 个答案:

答案 0 :(得分:35)

为什么不使用正确的多态性而不是switch-case?例如,在这里你可以用Python中的鸭子输入做什么:

比方说,alice.py

def do_stuff(data):
    print 'alice does stuff with %s' % data

比方说,bob.py

def do_stuff(data):
    print 'bob does stuff with %s' % data

然后在您的客户端代码中,例如main.py

import threading
import alice, bob

def get_work_data():
    return 'data'

def main():
    tasks = [alice.do_stuff, bob.do_stuff]
    data = get_work_data()
    for task in tasks:
        t = threading.Thread(target=task, args=(data,))
        t.start()

如果我需要澄清,请告诉我。

答案 1 :(得分:5)

import threading
from foobar import alice, bob, charles

data = get_work_data() # names_in_pep8 are more Pythonic than camelCased

for mod in [alice, bob, charles]:
    # mod is an object that represent a module
    worker = getattr(mod, 'do_work')
    # worker now is a reference to the function like alice.do_work
    t = threading.Thread(target=worker, args=[data])
    # uncomment following line if you don't want to block the program
    # until thread finishes on termination
    #t.daemon = True 
    t.start()

将您的逻辑放在相应模块的do_work函数中。

答案 2 :(得分:3)

顺序执行:

from foobar import alice, bob, charles

for fct in (alice, bob, charles):
    fct()

并行执行:

from threading import Thread
from foobar import alice, bob, charles

for fct in (alice, bob, charles):
    Thread(target=fct).start()

答案 3 :(得分:1)

Python可以将函数保存为对象。为了克服缺少开关的限制,我建议如下:

case_alice = lambda data : alice.spawnWorker(data)

my_dict[alice] = case_alice

形成一个字典来保存你的“案例”陈述。

让我更进一步:

data = getWorkData()
case_alice = lambda d : alice.spawnWorker( d )
case_bob = lambda d : bob.spawnWorker( d )
case_charles = lambda d : charles.spawnWorker( d )

switch = { alice : case_alice, bob : case_bob, charles : case_charles }
spawn = lambda person : switch[ person ]( data )
[ spawn( item ) for item in (alice, bob, charles )]