我有一系列'任务',我想在不同的线程中运行。任务将由单独的模块执行。每个都包含用于处理其任务的业务逻辑。
给定一个任务元组,我希望能够为每个模块生成一个新线程,如下所示。
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()方法中(我知道明显的问题,但我不想做任何假设)。
我的想法是在正确的轨道上还是有缺陷的(如果有缺陷 - 我错过了什么?)
答案 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 )]