私は最後にhttps://github.com/tyarkoni/transitions/issues/198のタイムアウトメカニズムを実装しようとしています。私は状態の入力時に(タイムアウト状態のコンストラクタのパラメータとして)デフォルトのタイムアウトを設定し、終了時にそれをキャンセルすることを目指します。階層型ステートマシンの定義済みタイムアウトの設定と取り消しに失敗しました(012:参照:https://github.com/tyarkoni/transitions/issues/198)
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/IPython/core/interactiveshell.py", line 2481, in safe_execfile
self.compile if kw['shell_futures'] else None)
File "/usr/local/lib/python2.7/dist-packages/IPython/utils/py3compat.py", line 289, in execfile
builtin_mod.execfile(filename, *where)
File "/home/sge/workspace_neon/VS_AREA51/ocpp16j_experimental/hierasms.py", line 143, in <module>
collector.model.collect(a='acall1') # collecting
File "/home/sge/workspace_neon/VS_AREA51/ocpp16j_experimental/plugged/transitions/core.py", line 248, in trigger
return self.machine._process(f)
File "/home/sge/workspace_neon/VS_AREA51/ocpp16j_experimental/plugged/transitions/core.py", line 590, in _process
return trigger()
File "/home/sge/workspace_neon/VS_AREA51/ocpp16j_experimental/plugged/transitions/extensions/nesting.py", line 131, in _trigger
if t.execute(event):
File "/home/sge/workspace_neon/VS_AREA51/ocpp16j_experimental/plugged/transitions/extensions/nesting.py", line 100, in execute
return super(NestedTransition, self).execute(event_data)
File "/home/sge/workspace_neon/VS_AREA51/ocpp16j_experimental/plugged/transitions/core.py", line 174, in execute
self._change_state(event_data)
File "/home/sge/workspace_neon/VS_AREA51/ocpp16j_experimental/plugged/transitions/extensions/nesting.py", line 108, in _change_state
lvl = source_state.exit_nested(event_data, dest_state)
File "/home/sge/workspace_neon/VS_AREA51/ocpp16j_experimental/plugged/transitions/extensions/nesting.py", line 81, in exit_nested
tmp_self.exit(event_data)
TypeError: exit() takes exactly 1 argument (2 given)
と、ここでのコード(Pythonの2.7.6/IPython 5.1.0/0.4.2トランジション):
from threading import Thread, Event
from transitions.extensions import HierarchicalMachine as Machine
from transitions.extensions.nesting import NestedState as State
# Set up logging
import logging
from transitions import logger
logger.setLevel(logging.DEBUG)
class Timeout(Thread):
def __init__(self, func, timeout, **kwargs):
# self.lgtout=logging.getLogger(".".join([__name__, self.__class__.__name__]))
super(Timeout, self).__init__()
self.func = func
self.kwargs = kwargs
self.cancelEvt=Event()
self.cancelEvt.clear() #make ready for delay
self.timeout = timeout
print '---->Starting countdown from: '+str(self.timeout)
self.start()
def run(self):
self.cancelEvt.wait(self.timeout)
if not self.cancelEvt.isSet():
print '---->Timeout of ' +str(self.timeout)+ ' occurred in thread'+str(self.ident)
self.func(**self.kwargs) # trigger the sm
else:
print '---->Timeout of ' +str(self.timeout)+ ' canceled in thread'+str(self.ident)
class TimeoutState(State):
def __init__(self, name, timeout=3, timeoutSmTrigger='timeOUT', *args, **kwargs):
self.timeout = timeout
self._timer=None
self.timeoutSmTrigger=timeoutSmTrigger
super(TimeoutState, self).__init__(name=name, *args, **kwargs)
print 'timeout state created: ',name
def enter(self, **kwargs):
# initialise timeout
print 'enter: '+str(kwargs)
timeout = kwargs.pop('timeout',self.timeout)
timeoutSmTrigger = kwargs.pop('timeoutSmTrigger',self.timeoutSmTrigger)
func = getattr(kwargs.get('model',None), timeoutSmTrigger)
self._timer = Timeout(func, timeout, **kwargs)
def exit(self, **kwargs):
print 'enter: '+str(kwargs)
if self._timer:
self._timer.cancelEvt.set()
class TimeoutMachine(Machine):
def __init__(self, name, states, transitions, initial, model=None):
super(TimeoutMachine,self).__init__(model=model, states=states, initial=initial, transitions=transitions,
send_event=False,
auto_transitions=False, ordered_transitions=False,
ignore_invalid_triggers=False, name=name, queued=False)
def _create_state(self, *args, **kwargs):
'''
Overwrite to create all the way states with timeout mechanism
'''
return TimeoutState(*args, **kwargs)
class CntModel(object):
def bcall(self,**kwargs):
print 'before increase: ',str(kwargs)
# logger.debug('---------bcall done')
'''
timeout indicator
'''
def timeOUT(self, **kwargs):
print 'Time out occurred'
count_states = [{'name':'1','timeout':'4','timeoutSmTrigger':'timeOUT'}, '2', '3', 'done']
# count_states = [{'name':'1'}, '2', '3', 'done']
count_trans = [
{'trigger':'increase', 'source':'1','dest':'2', 'before':'bcall'},
['increase', '2', '3'],
['decrease', '3', '2'],
['decrease', '2', '1'],
['done', '3', 'done'],
['reset', '*', '1']
]
counter = TimeoutMachine(name='Counter',states=count_states, transitions=count_trans, initial='1')
class ColModel(CntModel):
def acall(self, **kwargs):
print 'acall ',str(kwargs)
# logger.debug('-------acall done')
states = ['waiting', 'collecting', {'name': 'counting', 'children': counter}]
transitions = [
{'trigger':'collect', 'source':'*','dest':'collecting', 'after':'acall'},
['wait', '*', 'waiting'],
['count', 'collecting', 'counting_1']
]
colm = ColModel() #composed model
collector = TimeoutMachine(name='Collector', model=[colm], states=states, transitions=transitions, initial='waiting')
collector.model.collect(a='acall1') # collecting
collector.model.count() # let's see what we got
collector.model.increase(a='inc1') # counting_2
collector.model.increase(a='inc2') # counting_3
collector.model.done() # collector.state == counting_done
collector.model.wait() # collector.state == waiting
logger.handlers=[]
おかげ状態を終了しているときにエラーがoccures!
私は、提供されたコードサンプルを可能な限り煮詰めるのが良い方法と考えています。これにより、他の開発者があなたを助けてくれる可能性が高くなります。また、一般的で成功したデバッグ手順もあります。私は、多くの開発者がよく述べたStackoverflowの質問を作成しながら、彼らの問題の解決策を見つけたことは確かです。 – aleneum