class TaskResult(object): def __init__(self): self.__event = Event() self.__result = None def result(self): # 阻塞等结果 self.__event.wait() return self.__result def set_result(self, value): self.__result = value self.__event.set() # 标记执行完毕
def multi_thread(cam_nums, func, args): event = Event() try: event.set() pool = Pool(len(cam_nums)) for arg in args: arg.event = event results = pool.map(func, args) except KeyboardInterrupt: event.clear() finally: pool.close() pool.join() print('DONE')
class BaseActor(object): def __init__(self): """queue:Actor内部的邮箱队列""" self.__mailbox = Queue() def recv(self): """Actor接受消息""" msg = self.__mailbox.get() if msg is ActorExit: # 抛出异常(模版方法会处理) raise ActorExit return msg def send(self, msg): """Actor发送消息""" self.__mailbox.put(msg) def close(self): """发送结束标识""" self.send(ActorExit) def start(self): self.__terminated_event = Event() # 为Join服务 t = threading.Thread(target=self.__templet) t.setDaemon(True) # 设置为守护线程 t.start() def __templet(self): """模版方法(run会被子类重写)""" try: self.run() # 执行Run代码 except ActorExit: pass # 防止线程挂掉 finally: # 设置Event标识 self.__terminated_event.set() def join(self): # Event在set之后便结束等待 self.__terminated_event.wait() def run(self): """ 由子类实现即可,eg: while True: msg = self.recv() print(msg) """ pass
class SkillCore(SkillDescription): gen_id = IdGen() def __init__(self): """ @brief An abstract executable skill with a description (type, label, params, conditions), a state and progress code """ # Description self._id = SkillCore.gen_id.getId() self._type = "" self._label = "" self._description = SkillDescription() # Params self._params = params.ParamHandler() # Conditions self._pre_conditions = [] self._hold_conditions = [] self._post_conditions = [] # Execution self._state_change = Event() self._state = State.Uninitialized self._avg_time_keeper = TimeKeeper() self._time_keeper = TimeKeeper() self._progress_code = 0 self._progress_period = 0.0 self._progress_time = 0.0 self._progress_msg = "" self._expand_on_start = False # --------Class functions-------- def expand(self, skill): return def hasChildren(self): return False def _setState(self, state): self._state = state self._state_change.set() def _setProgress(self, msg, code=None): if code is None: code = self._progress_code + 1 self._progress_code = code self._progress_period = self._avg_time_keeper.get_avg_time() self._progress_time = self._time_keeper.time_from_start() self._progress_msg = str(msg) @property def id(self): return self._id @property def progress_code(self): return self._progress_code @property def progress_period(self): return self._progress_period @property def progress_time(self): return self._progress_time @property def progress_msg(self): return self._progress_msg @property def state(self): return self._state @property def expand_on_start(self): """ @brief Default False. If true, the skill will expand every time it is started. Used e.g. in a planner skill """ return self._expand_on_start def _resetDescription(self, other=None): if other: self._params.reset(self._description._params.merge(other._params)) else: self._params = deepcopy(self._description._params) self._pre_conditions = deepcopy(self._description._pre_conditions) self._hold_conditions = deepcopy(self._description._hold_conditions) self._post_conditions = deepcopy(self._description._post_conditions) def hasPreCond(self): return bool(self._pre_conditions) def checkPreCond(self, verbose=False): """ @brief Check pre-conditions. @param verbose (bool) Print error message when check fail @return A list of parameters that breaks the conditions, or an empty list if all are satisfied """ to_ret = list() err_msg = "" for c in self._pre_conditions: if not c.evaluate(self._params, self._wmi): err_msg += "{} Check failed. \n".format(c.getDescription()) if verbose: log.error(c.getDescription(), "ConditionCheck failed") to_ret += c.getKeys() self._setProgress(err_msg, -1) return list(set(to_ret)) def checkHoldCond(self, verbose=False): """ @brief Check hold-conditions. @param verbose (bool) Print error message when check fail @return A list of parameters that breaks the conditions, or an empty list if all are satisfied """ to_ret = list() err_msg = "" for c in self._hold_conditions: if not c.evaluate(self._params, self._wmi): err_msg += "{} Check failed. \n".format(c.getDescription()) if verbose: log.error("HoldConditionCheck failed", c.getDescription()) to_ret += c.getKeys() self._setProgress(err_msg, -2) return list(set(to_ret)) def hasPostCond(self): return bool(self._post_conditions) def checkPostCond(self, verbose=False): """ @brief Check post-conditions. @param verbose (bool) Print error message when check fail @return A list of parameters that breaks the conditions, or an empty list if all are satisfied """ to_ret = list() for c in self._post_conditions: if not c.evaluate(self._params, self._wmi): if verbose: log.error(c.getDescription(), "ConditionCheck failed") to_ret += c.getKeys() return list(set(to_ret)) # -------- Control functions-------- def preempt(self): if self.hasState(State.Running): self._setState(self.onPreempt()) if not self.onEnd(): self._setState(State.Failure) return self._state def getState(self): return self._state def hasState(self, state): return self._state == state def waitState(self, state, isset=True): if isset: # Xor? while self._state != state: # print 'Waiting set.. {}'.format(self._state) self._state_change.clear() self._state_change.wait() else: while self._state == state: # print 'Waiting not set.. {}'.format(self._state) self._state_change.clear() self._state_change.wait() # print 'State changed {}'.format(self._state) def reset(self): self.onReset() self._params.setDefault() self._time_keeper.reset() self._avg_time_keeper.reset() self._setProgress("", 0) self._setState(State.Idle) return self._state def start(self, params=None): if params: self.specifyParams(params, False) self._time_keeper.reset() if self.onStart(): self._setState(State.Running) self._setProgress("Start", 0) else: self._setState(State.Failure) return self._state def printInfo(self, verbose=False): s = "{}-{} ".format(self._type, self._label) if verbose: s += "[" s += self._params.printState() + ']\n' s += self.printConditions() else: s += "\n" return s def printState(self, verbose=False): s = "{}-{}({})".format(self.type[self.type.find(":") + 1:], self.label, self.state) if verbose: s += "[{}]".format(self.params.printState()) return s def printProgress(self): return "[{}] {}".format(self._progress_code, self._progress_msg) def specifyParamDefault(self, key, values): """ @brief Specify a value and set it as default value too @param key (string) Parameter key @param values Parameter value(s) """ if not self._params.hasParam(key): log.error( "specifyParamDefault", "No param '{}' found. Debug: {}".format( key, self.printInfo(True))) self._params.specifyDefault(key, values) def specifyParam(self, key, values): """ @brief Specify a parameter and update the input cache @param key (string) Parameter key @param values Parameter value(s) """ if not self._params.hasParam(key): log.error( "specifyParam", "No param '{}' found. Debug: {}".format( key, self.printInfo(True))) self._params.specify(key, values) def specifyParamsDefault(self, input_params): """ @brief Set the parameters and makes them default (they will no more be overwritten by specifyParams, even with keep_offline=False) @param input_params (dict) """ self._params.specifyParamsDefault(input_params) def specifyParams(self, input_params, keep_default=True): """ @brief Set the parameters @param input_params (dict) Parameters to set @param keep_default (bool) If True, params already specified are preserved """ self._params.specifyParams(input_params, keep_default) # -------- User's functions-------- def setDescription(self, description, label=""): """ @brief Description is a SkillDescription """ self._description = description self._type = description._type if label != "": self._label = label self._resetDescription() def startError(self, msg, code): """ @brief signal an error during the starting routine """ assert type(msg) == str assert type(code) == int self.fail(msg, code) return False def step(self, msg=""): """ @brief Set a running breakpoint """ assert type(msg) == str self._setProgress(msg) return State.Running def fail(self, msg, code): """ @brief Set a failure state """ assert type(msg) == str assert type(code) == int if code > 0: code *= -1 self._setProgress(msg, code) return State.Failure def success(self, msg=""): """ @brief Set a success state """ assert type(msg) == str self._setProgress(msg) return State.Success # -------- Virtual functions-------- def modifyDescription(self, skill): """ @brief Override to define additional parameters/condition over the skill """ pass def onReset(self): """ @brief Called when resetting. """ pass def onStart(self): """ @brief Called just before 1st execute @return (Bool) """ return True def onPreempt(self): """ @brief Called when skill is requested to stop. @return (State) """ self._setProgress("Preempted", -1) return State.Failure def execute(self): """ @brief Main execution function @return (State) """ raise NotImplementedError("Not implemented in abstract class") def onEnd(self): """ @brief Called just after last execute or preemption @return (Bool) """ return True
def do_GET(self): # отправка видео по запросу из плейлиста if re.match('.*p\d+\.ts', self.path): print('REQUEST', self.path) idx = int(re.match('.*p(\d).ts', self.path).groups()[0]) self.send_response(200, 'OK') self.send_header('content-type', 'video/vnd.dlna.mpeg-tts') self.end_headers() parts = PartsHandler.parts popen = PartsHandler.popen if parts[idx]['hosting'] == 'google': # через ffmpeg кусок скачивается и преобразуется в .ts popen = subprocess.Popen(parts[idx]['cmd'], stdout=subprocess.PIPE) # выхлоп отправляется напрямую по запросу while True: line = popen.stdout.readline() if line: try: self.wfile.write(line) except Exception as e: print('EXCEPTION: ', e) popen.stdout.close() popen.kill() else: popen.stdout.close() popen.kill() print('ffmpeg killed') break elif parts[idx]['hosting'] == 'big-sword': # из-за особенностей сервера big-sword качать пришлось # отдельно, pipe'ить в ffmpeg, а оттуда уже отправлять # код с дополнительным процессом ниже необходим, т.к. # баг в Popen под windows ffmpeg = subprocess.Popen(parts[idx]['cmd'], \ stdin=subprocess.PIPE, stdout=subprocess.PIPE) stop_event = Event() gvp = Process(target=self.get_video, args=(ffmpeg, parts[idx]['url'], stop_event)) gvp.start() while True: line = ffmpeg.stdout.readline() if line: try: self.wfile.write(line) except Exception as e: print('Exception occured when sending ffmpeg ' \ 'output:\n', e) break else: break ffmpeg.stdout.close() ffmpeg.kill() stop_event.set() gvp.join() # генерация и отправка плейлистов, при получении # в запросе elif re.search(r'playlist\.m3u8', self.path): if re.search(r'http://lh3.googleusercontent', self.path): hosting = 'google' elif re.search(r'\.big-sword', self.path): hosting = 'big-sword' else: return print('PLAYLIST REQUEST:', self.path) paths = uq(self.path) self.urls = paths.lstrip('/playlist.m3u8?').split(' ') PartsHandler.parts = get_video_info(self.urls, hosting) playlist = build_playlist(PartsHandler.parts) self.send_response(200, 'OK') self.send_header('Content-Length', len(playlist)) self.send_header('Content-Type', 'application/vnd.apple.mpegurl') self.end_headers() self.wfile.write(playlist.encode())