代码之家  ›  专栏  ›  技术社区  ›  maynull

如何在Python中使用带有协程的装饰器?

  •  0
  • maynull  · 技术社区  · 6 年前

    我正在尝试制作一个程序,它产生两个进程,它们彼此通信。我读过关于协程的书,认为这次采用它会更好,因为协程需要在使用前涂上底漆,所以我认为让一个装饰师自动这样做会更好。

    import multiprocessing as mp
    import random
    import time
    import os
    from datetime import datetime, timedelta
    from functools import wraps
    
    output, input = mp.Pipe()
    
    
    
    def co_deco(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            cr = func(*args, **kwargs)
            cr.send(None)
            return cr
        return wrapper
    
    class sender(mp.Process):
        def __init__(self, pipe):
            mp.Process.__init__(self)
            self.pipe = pipe
    
        def run(self):
            print('RECEIVER PID: ', os.getpid() )
            while True:
                self.pipe.send( random.randint(0,10) )
                time.sleep(1)
    
    class receiver(mp.Process):
        def __init__(self, pipe):
            mp.Process.__init__(self)
            self.pipe = pipe
    
        def run(self):
            while True:
                self.coroutine.send( self.pipe.recv() )
    
        @co_deco
        def coroutine(self):
            while True:
                msg = yield
                print( datetime.now(), msg )
    
    
    
    if __name__ == '__main__':
        mp.freeze_support()
    
        sen = sender(pipe=input)
        rec = receiver(pipe = output)
    
        sen.start()
        rec.start()
    

    sen 进程将随机整数发送到 rec 每秒处理一次。每当整数到达时, coroutine 方法 收入 )将其绑定到 msg 并按当前时间打印出来。

    我看到代码没有问题,但它显示一条错误消息:

    self.coroutine.send( self.pipe.recv() )
    AttributeError: 'function' object has no attribute 'send'
    

    我认为装饰连体衣有问题,但我不知道问题到底是什么以及如何解决。我想得到一些帮助。

    1 回复  |  直到 6 年前
        1
  •  5
  •   Bharel    6 年前

    def run(self):
        # Create and initialize the coroutine
        cr = self.coroutine()
    
        while True:
            # Send the data
            cr.send( self.pipe.recv() )
    

    def co_deco(func):
        cr = func()
        cr.send(None)
        return cr
    
    
    @co_deco
    def coroutine():
        while True:
            msg = yield
            print( datetime.now(), msg )
    

    def co_deco(func):
        @property
        @wraps(func)
        def wrapper(self, *args, **kwargs):
            try:
                # Get the coroutine from the instance object under a 
                # name with a leading underscore
                return getattr(self, "_" + func.__name__)
            except AttributeError:
                pass
    
            cr = func(self, *args, **kwargs)
            # Set the coroutine from the instance object under a 
            # name with a leading underscore
            setattr(self, "_" + func.__name__, cr)
            cr.send(None)
            return cr
        return wrapper
    
    
    @co_deco
    def coroutine(self):
        while True:
            msg = yield
            print( datetime.now(), msg )