def _pinger(self):
'''
A Controller can time us out if we are silent for too long. This
is especially true in JaaS, which has a fairly strict timeout.
To prevent timing out, we send a ping every ten seconds.
'''
async def _do_ping():
try:
await pinger_facade.Ping()
await asyncio.sleep(10, loop=self.loop)
except CancelledError:
pass
pinger_facade = client.PingerFacade.from_connection(self)
while self.monitor.status == Monitor.CONNECTED:
try:
await utils.run_with_interrupt(
_do_ping(),
self.monitor.close_called,
loop=self.loop)
except websockets.ConnectionClosed:
pass
python类CancelledError()的实例源码
def _wait_for_done(self, timeout):
"""
Will not return until either timeout expires or future becomes "done".
There is one potential deadlock situation here:
The deadlock occurs if we await_result while at the same
time, this future needs to await_result from another future
---> To be safe, don't use await_result() in a Qt slot...
"""
if self.cancelled():
raise CancelledError("Future was cancelled") # pragma: no-cover
if not self.done():
self.timer_timeout = None
if (timeout is not None) and timeout > 0:
self._timer_timeout = MainThreadTimer(timeout*1000)
self._timer_timeout.timeout.connect(self._exit_loop)
self._timer_timeout.start()
self.loop = QtCore.QEventLoop()
self.add_done_callback(self._exit_loop)
self.loop.exec_()
if self._timer_timeout is not None:
if not self._timer_timeout.isActive():
return TimeoutError("Timeout occured") # pragma: no-cover
else:
self._timer_timeout.stop()
def await_exception(self, timeout=None): # pragma: no-cover
"""
Return the exception raised by the call that the future represents.
Args:
timeout: The number of seconds to wait for the exception if the
future isn't done. If None, then there is no limit on the wait
time.
Returns:
The exception raised by the call that the future represents or None
if the call completed without raising.
Raises:
CancelledError: If the future was cancelled.
TimeoutError: If the future didn't finish executing before the
given timeout.
"""
self._wait_for_done(timeout)
return self.exception()
def run_task(self) -> None:
'''Execute the task inside the asyncio event loop. Track the time it
takes to run, and log when it starts/stops. After `INTERVAL` seconds,
if/once the task has finished running, run it again until `stop()`
is called.'''
while self.running:
try:
Log.debug('executing periodic task %s', self.name)
before = self.time()
await self.run()
total = self.time() - before
Log.debug('finished periodic task %s in %.1f seconds',
self.name, total)
sleep = self.INTERVAL - total
if sleep > 0:
await self.sleep(sleep)
except CancelledError:
Log.debug('cancelled periodic task %s', self.name)
raise
except Exception:
Log.exception('exception in periodic task %s', self.name)
def _process_future(self, future, timeout=None, sigint=False):
try:
msg = future.result(timeout)
except CancelledError:
# This error is raised when Task.cancel is called on
# disconnect from the validator in stream.py, for
# this future.
return
if msg is RECONNECT_EVENT:
if sigint is False:
LOGGER.info("reregistering with validator")
self._stream.wait_for_ready()
self._register()
else:
LOGGER.debug(
'received message of type: %s',
Message.MessageType.Name(msg.message_type))
if msg.message_type == Message.PING_REQUEST:
self._stream.send_back(
message_type=Message.PING_RESPONSE,
correlation_id=msg.correlation_id,
content=PingResponse().SerializeToString())
return
self._process(msg)
def _receive_message(self):
"""
Internal coroutine for receiving messages
"""
while True:
try:
if self._socket.getsockopt(zmq.TYPE) == zmq.ROUTER:
zmq_identity, msg_bytes = \
yield from self._socket.recv_multipart()
self._received_from_identity(zmq_identity)
self._dispatcher_queue.put_nowait(
(zmq_identity, msg_bytes))
else:
msg_bytes = yield from self._socket.recv()
self._last_message_time = time.time()
self._dispatcher_queue.put_nowait((None, msg_bytes))
except CancelledError:
# The concurrent.futures.CancelledError is caught by asyncio
# when the Task associated with the coroutine is cancelled.
# The raise is required to stop this component.
raise
except Exception as e: # pylint: disable=broad-except
LOGGER.exception("Received a message on address %s that "
"caused an error: %s", self._address, e)
def a_input(prompt: str) -> str:
"""Async input prompt."""
readable = [] # type: List[int]
print(prompt, end='')
sys.stdout.flush()
while not readable:
readable, _, _ = select.select([sys.stdin], [], [], 0)
try:
await asyncio.sleep(0.1)
except futures.CancelledError:
print("input cancelled...")
termios.tcflush(sys.stdin, termios.TCIFLUSH)
raise
return sys.stdin.readline().rstrip()
# [ Classes ]
def run_event_loop(self, close_after=None):
self._loop.add_signal_handler(signal.SIGHUP, self.shutdown)
self._loop.add_signal_handler(signal.SIGINT, self.shutdown)
self._loop.add_signal_handler(signal.SIGTERM, self.shutdown)
try:
self._loop.run_until_complete(asyncio.wait([
self._close_after(close_after),
self._main(),
self._listen_to_queue()
]))
except CancelledError:
self._log('CancelledError raised: closing event loop.')
with self._lock:
self._run_complete = True
finally:
self._loop.close()
def run_event_loop(self, close_after=None):
self._loop.add_signal_handler(signal.SIGHUP, self.shutdown)
self._loop.add_signal_handler(signal.SIGINT, self.shutdown)
self._loop.add_signal_handler(signal.SIGTERM, self.shutdown)
try:
self._loop.run_until_complete(asyncio.wait([
self._close_after(close_after),
self._main(),
self._listen_to_queue()
]))
except CancelledError:
self._log('CancelledError raised: closing event loop.')
with self._lock:
self._run_complete = True
finally:
self._loop.close()
def _receiver(self):
try:
while self.is_open:
result = await utils.run_with_interrupt(
self.ws.recv(),
self.monitor.close_called,
loop=self.loop)
if self.monitor.close_called.is_set():
break
if result is not None:
result = json.loads(result)
await self.messages.put(result['request-id'], result)
except CancelledError:
pass
except websockets.ConnectionClosed as e:
log.warning('Receiver: Connection closed, reconnecting')
await self.messages.put_all(e)
# the reconnect has to be done as a task because the receiver will
# be cancelled by the reconnect and we don't want the reconnect
# to be aborted half-way through
self.loop.create_task(self.reconnect())
return
except Exception as e:
log.exception("Error in receiver")
# make pending listeners aware of the error
await self.messages.put_all(e)
raise
def worker(self, id_):
loop = asyncio.get_event_loop()
asyncio.Task.current_task().logging_id = 'wk%02d' % (id_,)
while True:
logger.debug("Worker %d waiting.", id_)
item = yield from self.queue.get()
logger.debug(
"Worker %d working on %s %s.",
id_, item.__class__.__name__, item,
)
task = loop.create_task(item())
try:
res = yield from task
item.set_result(res)
except CancelledError:
item.cancel()
logger.warn("Cancel of %s", item)
except Exception as e:
item.set_exception(e)
if SETTINGS.VERBOSE or SETTINGS.DEBUG:
logger.exception("Failed to process %s: %s", item, e)
else:
logger.error("Failed to process %s: %s", item, e)
finally:
self.queue.task_done()
def test_result_with_timeout(self):
self.assertRaises(futures.TimeoutError,
PENDING_FUTURE.result, timeout=0)
self.assertRaises(futures.TimeoutError,
RUNNING_FUTURE.result, timeout=0)
self.assertRaises(futures.CancelledError,
CANCELLED_FUTURE.result, timeout=0)
self.assertRaises(futures.CancelledError,
CANCELLED_AND_NOTIFIED_FUTURE.result, timeout=0)
self.assertRaises(IOError, EXCEPTION_FUTURE.result, timeout=0)
self.assertEqual(SUCCESSFUL_FUTURE.result(timeout=0), 42)
def test_exception_with_timeout(self):
self.assertRaises(futures.TimeoutError,
PENDING_FUTURE.exception, timeout=0)
self.assertRaises(futures.TimeoutError,
RUNNING_FUTURE.exception, timeout=0)
self.assertRaises(futures.CancelledError,
CANCELLED_FUTURE.exception, timeout=0)
self.assertRaises(futures.CancelledError,
CANCELLED_AND_NOTIFIED_FUTURE.exception, timeout=0)
self.assertTrue(isinstance(EXCEPTION_FUTURE.exception(timeout=0),
IOError))
self.assertEqual(SUCCESSFUL_FUTURE.exception(timeout=0), None)
def cancel(self):
"""Request that this task cancel itself.
This arranges for a CancelledError to be thrown into the
wrapped coroutine on the next cycle through the event loop.
The coroutine then has a chance to clean up or even deny
the request using try/except/finally.
Unlike Future.cancel, this does not guarantee that the
task will be cancelled: the exception might be caught and
acted upon, delaying cancellation of the task or preventing
cancellation completely. The task may also return a value or
raise a different exception.
Immediately after this method is called, Task.cancelled() will
not return True (unless the task was already cancelled). A
task will be marked as cancelled when the wrapped coroutine
terminates with a CancelledError exception (even if cancel()
was not called).
"""
if self.done():
return False
if self._fut_waiter is not None:
if self._fut_waiter.cancel():
# Leave self._fut_waiter; it may be a Task that
# catches and ignores the cancellation so we may have
# to cancel it again later.
return True
# It must be the case that self._step is already scheduled.
self._must_cancel = True
return True
#
# ????:
#
def run_tasks(self):
""" Run the tasks attached to the instance """
await self.setup
tasks = self.get_tasks()
self._gathered_tasks = asyncio.gather(*tasks, loop=self.loop)
try:
await self._gathered_tasks
except CancelledError:
pass
def await_result(self, timeout=None):
"""
Return the result of the call that the future represents.
Will not return until either timeout expires or future becomes "done".
There is one potential deadlock situation here:
The deadlock occurs if we await_result while at the same
time, this future needs to await_result from another future since
the eventloop will be blocked.
---> To be safe, don't use await_result() in a Qt slot. You should
rather use result() and add_done_callback() instead.
Args:
timeout: The number of seconds to wait for the result if the future
isn't done. If None, then there is no limit on the wait time.
Returns:
The result of the call that the future represents.
Raises:
CancelledError: If the future was cancelled.
TimeoutError: If the future didn't finish executing before the
given timeout.
Exception: If the call raised then that exception will be raised.
"""
self._wait_for_done(timeout)
return self.result()
def test_result_with_timeout(self):
self.assertRaises(futures.TimeoutError,
PENDING_FUTURE.result, timeout=0)
self.assertRaises(futures.TimeoutError,
RUNNING_FUTURE.result, timeout=0)
self.assertRaises(futures.CancelledError,
CANCELLED_FUTURE.result, timeout=0)
self.assertRaises(futures.CancelledError,
CANCELLED_AND_NOTIFIED_FUTURE.result, timeout=0)
self.assertRaises(IOError, EXCEPTION_FUTURE.result, timeout=0)
self.assertEqual(SUCCESSFUL_FUTURE.result(timeout=0), 42)
def test_exception_with_timeout(self):
self.assertRaises(futures.TimeoutError,
PENDING_FUTURE.exception, timeout=0)
self.assertRaises(futures.TimeoutError,
RUNNING_FUTURE.exception, timeout=0)
self.assertRaises(futures.CancelledError,
CANCELLED_FUTURE.exception, timeout=0)
self.assertRaises(futures.CancelledError,
CANCELLED_AND_NOTIFIED_FUTURE.exception, timeout=0)
self.assertTrue(isinstance(EXCEPTION_FUTURE.exception(timeout=0),
IOError))
self.assertEqual(SUCCESSFUL_FUTURE.exception(timeout=0), None)
def deactivate(self):
print("Please press enter to kill the readline loop.")
self.run_loop = False
try:
self.task.cancel()
if self.read_task:
self.read_task.cancel()
except CancelledError:
pass
def _listen(self):
conf = self.config_manager.config
while self.run_loop:
try:
t_input = await self._readline()
except CancelledError:
raise
except Exception:
self.logger.exception("Exception waiting for input: ", exc_info=True)
continue
args = shlex.split(t_input)
if not args:
continue
elif args[0].lower() in self.con_commands:
try:
await self.con_commands[args[0].lower()](args[1:])
except ConsoleCommandSyntaxError as e:
err = str(e) if str(e) else "No additional information."
print("Syntax error: " + err)
except CancelledError:
raise
except Exception:
self.logger.exception("Exception while running console command: ", exc_info=True)
else:
print("Invalid command.")
# Console command functions
def download(loglevel, savedir, path):
try:
os.environ['loglevel'] = loglevel
logger = get_logger()
if savedir == '.':
savedir = b''
elif os.path.exists(savedir):
savedir = bytes(savedir.encode('utf-8'))
else:
logger.info("Directory {} doesn't exist".format(savedir))
exit(1)
loop = asyncio.get_event_loop()
loop.set_debug(True)
client = Client()
task = loop.create_task(client.download(path, savedir))
try:
loop.run_until_complete(task)
except CancelledError:
logging.warning('Event was cancelled')
finally:
task.cancel()
try:
loop.run_until_complete(task)
except Exception:
pass
loop.close()
except (bencodepy.DecodingError,
FileNotFoundError) as e:
logger.error(e)
def upload(loglevel, path):
try:
os.environ['loglevel'] = loglevel
logger = get_logger()
loop = asyncio.get_event_loop()
loop.set_debug(True)
# loop.slow_callback_duration = 0.001
# warnings.simplefilter('always', ResourceWarning)
client = Client()
client.parse(path)
task = loop.create_task(client.upload())
server = run_server(port=51213, torrent=client.torrent)
server_task = loop.create_task(server)
try:
loop.run_until_complete(
asyncio.wait([task, server_task]))
loop.run_forever()
except CancelledError:
logging.warning('Event was cancelled')
except Exception as e:
logging.info(e)
except KeyboardInterrupt:
logging.info('Received key board interrupt')
finally:
task.cancel()
server_task.cancel()
try:
logger.info('Smothly disconnecting')
client.close()
except Exception:
pass
loop.close()
except (bencodepy.DecodingError,
FileNotFoundError) as e:
logger.error(e)
def __anext__(self):
# Read data from the socket. When we have enough data to parse, parse
# it and return the message. Until then keep reading from stream
while True:
try:
if self.buffer:
message = self.parse()
if message:
return message
logger.debug('I m stuck at reading from socket')
data = await self.reader.read(
PeerStreamIterator.CHUNK_SIZE)
if data:
self.buffer += data
message = self.parse()
if message:
return message
except ConnectionResetError:
logging.debug('Connection closed by peer')
raise StopAsyncIteration()
except CancelledError:
raise StopAsyncIteration()
except StopAsyncIteration as e:
# Cath to stop logging
raise e
except Exception:
logging.exception('Error when iterating over stream!')
raise StopAsyncIteration()
raise StopAsyncIteration()
def _kill_subprocess(self, proc):
# type: (Optional[Process]) -> None
"""Helper method; send SIGTERM/SIGKILL to a subprocess.
This method first sends SIGTERM to the subprocess. If the process hasn't terminated
after a given timeout, it sends SIGKILL.
Parameter
---------
proc : Optional[Process]
the process to attempt to terminate. If None, this method does nothing.
"""
if proc is not None:
if proc.returncode is None:
try:
proc.terminate()
try:
await asyncio.shield(asyncio.wait_for(proc.wait(), self._cancel_timeout))
except CancelledError:
pass
if proc.returncode is None:
proc.kill()
try:
await asyncio.shield(asyncio.wait_for(proc.wait(), self._cancel_timeout))
except CancelledError:
pass
except ProcessLookupError:
pass
def _async_subscribe(self, callback=None): # pylint: disable=too-many-branches
""" event loop """
while True:
if self._reader is None:
yield from asyncio.sleep(0.1)
continue
try:
msg = yield from self._reader.readline()
except TimeoutError:
print('[E] Connection got timed out, try to reconnect...')
yield from self._connect(self._host)
except ConnectionResetError:
print('[E] Peer reset our connection, try to reconnect...')
yield from self._connect(self._host)
except (GeneratorExit, CancelledError):
print('[I] Cancelling event loop...')
return
except: # pylint: disable=bare-except
print('[E] Ignoring', sys.exc_info()[0])
if self._verbose:
print(msg.decode())
# simplejson doesnt need to decode from byte to ascii
data = json.loads(msg.decode())
if self._verbose:
print('DATA:')
print(data)
try:
self._parse_command(data)
except AioHeosException as exc:
print('[E]', exc)
if self._verbose:
print('MSG', msg)
print('MSG decoded', msg.decode())
print('MSG json', data)
continue
if callback:
if self._verbose:
print('TRIGGER CALLBACK')
self._loop.create_task(self._callback_wrapper(callback))
def launch_process(executor, callback, **kwargs):
try:
while True:
p = mp.Process(target=callback, kwargs=kwargs)
p.start()
loop = asyncio.get_event_loop()
await loop.run_in_executor(executor, wait_for, p)
except CancelledError:
pass
except KeyboardInterrupt:
pass
def game_watch(self):
if self.gamewatch_running:
return
self.gamewatch_running = True
try:
lop = datetime.datetime(2015, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
asmbot.log("Gamewatch for shard {} initialized".format(self.shard_id), tag="ASM GAME")
while not self.is_closed:
cop = datetime.datetime.now(datetime.timezone.utc)
tdelta = cop - lop
if tdelta.seconds >= 900:
lop = cop
await self.change_presence(game=discord.Game(name="LLVM"))
await asyncio.sleep(0.1)
except CancelledError:
pass
except Exception as e:
asmbot.logex(e, tag="ASM GAME")
finally:
self.gamewatch_running = False
asmbot.log("Gamewatch for shard {} closed".format(self.shard_id), tag="ASM GAME")
# Error handling
def run(self):
"""Run the bot."""
with ClientSession() as session:
url = self.url + "?"
url += urlencode({"v": self.API_VERSION, "encoding": json})
while not self.running.done():
print("Bot is connecting...")
self.ws_running = asyncio.Future()
async with session.ws_connect(url) as ws:
self.ws = ws
while not self.running.done():
# Reading the message.
data = await self._receive()
if not data:
break
await self._handle(data)
# Cleanup
self.futures = [f
for f in self.futures if not f.done()]
# Close the tasks
# Wait for them.
print("Bot is closing...")
self.ws_running.cancel()
while self.futures:
try:
await asyncio.gather(*self.futures)
except CancelledError:
pass
self.futures = [f
for f in self.futures if not f.done()]
def test_result_with_timeout(self):
self.assertRaises(futures.TimeoutError,
PENDING_FUTURE.result, timeout=0)
self.assertRaises(futures.TimeoutError,
RUNNING_FUTURE.result, timeout=0)
self.assertRaises(futures.CancelledError,
CANCELLED_FUTURE.result, timeout=0)
self.assertRaises(futures.CancelledError,
CANCELLED_AND_NOTIFIED_FUTURE.result, timeout=0)
self.assertRaises(OSError, EXCEPTION_FUTURE.result, timeout=0)
self.assertEqual(SUCCESSFUL_FUTURE.result(timeout=0), 42)
def test_exception_with_timeout(self):
self.assertRaises(futures.TimeoutError,
PENDING_FUTURE.exception, timeout=0)
self.assertRaises(futures.TimeoutError,
RUNNING_FUTURE.exception, timeout=0)
self.assertRaises(futures.CancelledError,
CANCELLED_FUTURE.exception, timeout=0)
self.assertRaises(futures.CancelledError,
CANCELLED_AND_NOTIFIED_FUTURE.exception, timeout=0)
self.assertTrue(isinstance(EXCEPTION_FUTURE.exception(timeout=0),
OSError))
self.assertEqual(SUCCESSFUL_FUTURE.exception(timeout=0), None)