繁体   English   中英

如何将函数和参数放入python队列?

[英]how to put a function and arguments into python queue?

我有一个包含2个线程的python程序(让我们将它们命名为'source'和'destination')。 源线程有时会使用一些参数将消息发布到目标线程。 比目标线程选择一条消息,它必须使用保存在消息中的历史记录调用相应的函数。

这个任务可以通过多种方式解决。 容易的是在目标线程的消息选择周期中调整一个大的'if ... if..if'并根据收到的消息类型和保存的参数调用函数。 但这将导致巨大的代码(或大查找表),并且添加新的消息/处理函数将演变为在消息选择周期中编写代码的额外步骤。

由于python将函数视为第一类对象并具有元组,因此我想在消息中放置函数和参数,因此,目标线程选择一条消息,它只是调用保存在消息中的函数,而不知道它是什么函数。

我可以为具有指定数量的参数的函数编写代码:

from Queue import *
from thread import *
from time import *

q = Queue()

def HandleMsg( arg1, arg2 ) :
  print arg1, arg2

def HandleAnotherMsg( arg1, arg2, arg3 ) :
  print arg1, arg2, arg3

def DestinationThread( a ) :
  while True :
    (f, a, b) = q.get()
    f( a, b )

start_new_thread( DestinationThread, ( 0, ) )
print "start"
sleep( 1 )
q.put( (HandleMsg, 1, 2) )
sleep( 1 )
print "stop"

问题是:如何修改代码,以便我可以把()一个函数与队列中的任意数量的参数放在一起? 例如HandleAnotherMsg()? 使用q.put((HandleAnotherMsg,1,2,3))会出现编译错误:(

很简单:

def DestinationThread( a ) :
  while True :
    items = q.get()
    func = items[0]
    args = items[1:]
    func(*args)

另一个有趣的选择就是传入一个lambda。

q.put(lambda: HandleMsg(1,2))
q.put(lambda: HandleAnother(8, "hello", extra="foo"))

def DestinationThread() :
   while True :
      f = q.get()
      f()
from Queue import *
from thread import *
from time import *

q = Queue()

def HandleMsg( arg1, arg2 ) :
  print arg1, arg2

def HandleAnotherMsg( arg1, arg2, arg3 ) :
  print arg1, arg2, arg3

def DestinationThread() :
  while True :
    f, args = q.get()
    f(*args)

start_new_thread( DestinationThread, tuple() )
print "start"
sleep( 1 )
q.put( (HandleMsg, [1, 2]) )
sleep( 1 )
q.put( (HandleAnotherMsg, [1, 2, 3]) )
sleep( 1 )
print "stop"

我之前使用过类似的构造:

class Call:
    def __init__(self, fn, *args, **kwargs):
        self.fn = fn
        self.args = args
        self.kwargs = kwargs

    def __call__(self):
        return self.fn(*self.args, **self.kwargs)


x = Call(zip, [0,1], [2,3], [4,5])

然后,您应该能够将x传递给另一个线程并从那里调用它:

x() # returns the same as zip([0,1], [2,3], [4,5])

听起来你想使用apply()内在函数或其后继者:

def f(x. y):
   print x+y

args = ( 1, 2 )

apply(f, args)   # old way

f(*args)        # new way

您可以使用run方法创建抽象消息类。 然后对于需要通过队列传输的每个函数,子类并将该函数实现为run方法。 发送线程将创建正确子类的实例并将其放入队列中。 接收线程将从队列中获取一个对象并盲目地执行run方法。

这通常称为命令模式(Gamma等)

例:

class Message (object):
    """abstract message class"""
    def __init__(self, **kwargs):
        self.kwargs = kwargs

    def run(self):
        pass


class MessageOne (Message):
    """one message class"""
    def run(self):
         # perform this emssage's action using the kwargs

发件人将实例化并发送消息:

queue.put(MessageOne(one='Eins', two='Deux'))

接收者只需获取一个消息对象并执行它运行方法(无需通过可用的消息类型)...:

msg = queue.get()
msg.run()

你为什么不把Queue子类化?


class MyQueue(Queue):
  # by using *args, you can have a variable number of arguments
  def put(self,*args):
    for arg in args:
       Queue.put(self,arg)

或者,你为什么不把名单?


list = [function_obj]
for arg in function_args:
   list.append(arg)
queue.put(list)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM