2016-08-23 5 views
3

これは私の現在のコードです:この例ではasyncioを使ってn秒間に関数を再スケジュールするためのpythonデコレータ関数を作るにはどうすればよいですか?

import asyncio 
import serial 


def repeat(seconds): 
    def wrap(func): 
     def decorated(*args): 
      loop = asyncio.get_event_loop() 
      loop.call_at(loop.time() + seconds, decorated, *args) 
      print('scheduled') 
      func(*args) 
      return func 
     return decorated 
    return wrap 


@repeat(10) 
def send_command(ser, text): 
    try: 
     if text == 'DATA': 
      print("\nSending Data Request") 
      ser.write(b'\n022022') 
     elif text == 'STAY': 
      print("\nInmediate Stay ARM") 
      ser.write(b'\n0640010002044D') 
     elif text == 'AWAY': 
      print("\nInmediate Away ARM") 
      ser.write(b'\n0640010003044E') 
     elif text == 'DISARM': 
      print("\nDISARM") 
      ser.write(b'\n0940010001040700055B') 
     elif text == 'CHIME': 
      print("\nChime toggle") 
      ser.write(b'\n0640010007014F') 
    except serial.SerialException as e: 
     raise e 


if __name__ == '__main__': 

    ser = serial.Serial('/dev/ttyUSB0', 9600, parity=serial.PARITY_ODD, write_timeout=0, timeout=0) 

    loop = asyncio.get_event_loop() 
    loop.call_at(loop.time() + 5, send_command, ser, 'DATA') 
    loop.run_forever() 

私はその後5秒と10秒ごとに実行するようにsend_command機能をスケジュールしようとしています。それは動作するようですが、私はちょっとloop.call_at(loop.time() + seconds, decorated, *args)コールと混同しています。コメントは感謝します。

+0

がloop.call_at' 'についてコメントはない、あなたのコードは、戻りfunc''で働いていないようです'func(* args)'でなければなりません –

+0

'loop.call_at'のどの部分があなたを混乱させるのでしょうか? [doc](https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.call_at)によれば、指定された場所で呼び出されるコールバック( 'decorated')をスケジュールするだけです(loop.time()+ seconds') –

+0

私は実際の関数呼び出しfunc(* args)を含んでいませんでした。既に編集済みです。私は内側の機能(装飾)の呼び出しと混乱して、将来の予定に変更します。 –

答えて

1

コードは問題ありません(ただし、デコレータ内でfuncの結果を返す必要があることを除いて)、少し改善しました。

それは、合成例を参照し、テストする方が簡単です:

import asyncio 
import functools 


def repeat(seconds): 
    def wrap(func): 
     @functools.wraps(func) # see http://stackoverflow.com/q/308999/1113207 
     def decorated(*args, **kwargs): 
      # We should call func that decorated again to 
      # force decorator's `call_at` code to execute again: 
      loop = asyncio.get_event_loop() 
      loop.call_at(
       loop.time() + seconds, 
       functools.partial(decorated, *args, **kwargs) # see http://stackoverflow.com/q/3252228/1113207 
      ) 
      # We should return result of func's excecution: 
      return func(*args, **kwargs) 
     return decorated 
    return wrap 


@repeat(2) 
def send_command(): 
    print('send_command') 


async def main(): 
    send_command() # call once, rescheduling started 

    for i in range(10): 
     print(i) 
     await asyncio.sleep(1) 


if __name__ == "__main__": 
    loop = asyncio.get_event_loop() 
    loop.run_until_complete(main()) 

は出力:

send_command 
0 
1 
send_command 
2 
3 
send_command 
4 
5 
send_command 
6 
7 
send_command 
8 
9 
send_command 
[Finished in 10.3s] 
+0

コメントと推奨事項をありがとう! –

関連する問題