def test_handle_callback_exception(self): # IOLoop.handle_callback_exception can be overridden to catch # exceptions in callbacks. def handle_callback_exception(callback): self.assertIs(sys.exc_info()[0], ZeroDivisionError) self.stop() self.io_loop.handle_callback_exception = handle_callback_exception with NullContext(): # remove the test StackContext that would see this uncaught # exception as a test failure. self.io_loop.add_callback(lambda: 1 / 0) self.wait()
def test_exception_logging_native_coro(self): """The IOLoop examines exceptions from awaitables and logs them.""" namespace = exec_test(globals(), locals(), """ async def callback(): # Stop the IOLoop two iterations after raising an exception # to give the exception time to be logged. self.io_loop.add_callback(self.io_loop.add_callback, self.stop) 1 / 0 """) with NullContext(): self.io_loop.add_callback(namespace["callback"]) with ExpectLog(app_log, "Exception in callback"): self.wait()
def test_read_callback_error(self): # Test that IOStream sets its exc_info when a read callback throws server, client = self.make_iostream_pair() try: server.set_close_callback(self.stop) with ExpectLog(app_log, "(Uncaught exception|Exception in callback)"): # Clear ExceptionStackContext so IOStream catches error with NullContext(): server.read_bytes(1, callback=lambda data: 1 / 0) client.write(b"1") self.wait() self.assertTrue(isinstance(server.error, ZeroDivisionError)) finally: server.close() client.close()
def addWriter(self, writer): if writer in self._writers: return fd = writer.fileno() self._writers[writer] = fd if fd in self._fds: (reader, _) = self._fds[fd] self._fds[fd] = (reader, writer) if reader: # We already registered this fd for read events, # update it for write events as well. self._io_loop.update_handler(fd, IOLoop.READ | IOLoop.WRITE) else: with NullContext(): self._fds[fd] = (None, writer) self._io_loop.add_handler(fd, self._invoke_callback, IOLoop.WRITE)
def addReader(self, reader): if reader in self._readers: # Don't add the reader if it's already there return fd = reader.fileno() self._readers[reader] = fd if fd in self._fds: (_, writer) = self._fds[fd] self._fds[fd] = (reader, writer) if writer: # We already registered this fd for write events, # update it for read events as well. self._io_loop.update_handler(fd, IOLoop.READ | IOLoop.WRITE) else: with NullContext(): self._fds[fd] = (reader, None) self._io_loop.add_handler(fd, self._invoke_callback, IOLoop.READ)
def get_page(self): def _waited_callback(name): return self.finish_group.add(partial(_callback, name, self)) self.json.put({'page': RequestContext.get('handler_name')}) self.add_callback(_waited_callback('callback')) with NullContext(): self.add_callback(_waited_callback('null_context_callback')) get_executor('threaded').submit(_waited_callback('executor')) self.add_future(self.run_coroutine(), self.finish_group.add_notification()) future = self.post_url(self.request.host + self.request.uri) future.add_done_callback(_waited_callback('future'))
def gmoment(): ''' Similar to :func:`tornado.gen.moment`, yields the IOLoop for a single iteration from inside a groutine. ''' gr = greenlet.getcurrent() assert gr.parent is not None, "gmoment() can only be called from functions that have the @greenado.groutine decorator in the call stack." io_loop = IOLoop.current() def _finish(): gr.switch() io_loop.add_callback(_finish) with NullContext(): gr.parent.switch()
def wait(self, condition=None, timeout=5): if not self._AsyncTestCase__stopped: if timeout: def timeout_func(): try: raise self.failureException( 'Async operation timed out after %d seconds' % timeout) except Exception: self._AsyncTestCase__failure = sys.exc_info() self.stop() self.timeout_handle = self.io_loop.add_timeout( time.time() + timeout, timeout_func) while True: self._AsyncTestCase__running = True with NullContext(): # Wipe out the StackContext that was established in # self.run() so that all callbacks executed inside the # IOLoop will re-run it. self.io_loop.start() if (self._AsyncTestCase__failure is not None or condition is None or condition()): break if self.timeout_handle: self.io_loop.remove_timeout(self.timeout_handle) self.timeout_handle = None assert self._AsyncTestCase__stopped self._AsyncTestCase__stopped = False if self._AsyncTestCase__failure is not None: # 2to3 isn't smart enough to convert three-argument raise # statements correctly in some cases. if isinstance(self._AsyncTestCase__failure[1], self._AsyncTestCase__failure[0]): raise self._AsyncTestCase__failure[ 1], None, self._AsyncTestCase__failure[2] else: raise self._AsyncTestCase__failure[ 0], self._AsyncTestCase__failure[ 1], self._AsyncTestCase__failure[2] result = self._AsyncTestCase__stop_args self._AsyncTestCase__stop_args = None return result
def wait(self, condition=None, timeout=5): """Runs the IOLoop until stop is called or timeout has passed. In the event of a timeout, an exception will be thrown. If condition is not None, the IOLoop will be restarted after stop() until condition() returns true. """ if not self.__stopped: if timeout: def timeout_func(): try: raise self.failureException( 'Async operation timed out after %d seconds' % timeout) except Exception: self.__failure = sys.exc_info() self.stop() self.io_loop.add_timeout(time.time() + timeout, timeout_func) while True: self.__running = True with NullContext(): # Wipe out the StackContext that was established in # self.run() so that all callbacks executed inside the # IOLoop will re-run it. self.io_loop.start() if (self.__failure is not None or condition is None or condition()): break assert self.__stopped self.__stopped = False if self.__failure is not None: # 2to3 isn't smart enough to convert three-argument raise # statements correctly in some cases. if isinstance(self.__failure[1], self.__failure[0]): raise self.__failure[1].with_traceback(self.__failure[2]) else: raise self.__failure[0](self.__failure[1]).with_traceback( self.__failure[2]) result = self.__stop_args self.__stop_args = None return result
def wrapper(*args, **kwargs): # When this function gets updated, update gcall also! future = concurrent.TracebackFuture() def greenlet_base(): try: result = f(*args, **kwargs) except Exception: future.set_exc_info(sys.exc_info()) else: future.set_result(result) gr = greenlet.greenlet(sc_wrap(greenlet_base)) with NullContext(): gr.switch() return future
def forward(self, encode_result): future = TracebackFuture() def handle_resp(resp): f = resp.get(_RESP_FUTURE) or future err = resp.get(RESP_ERR) result = resp.get(RESP_RESULT) if err: f.set_exception(err) else: f.set_result(result) with NullContext(): if self.__conn is None or not self.__conn.con_ok(): self.__conn = _PrxConn(handle_resp, self.__svr_addr) self.__conn.connect() self.__conn.write(future, encode_result) return future
def test_final_callback_stack_context(self): # The final callback should be run outside of the httpclient's # stack_context. We want to ensure that there is not stack_context # between the user's callback and the IOLoop, so monkey-patch # IOLoop.handle_callback_exception and disable the test harness's # context with a NullContext. # Note that this does not apply to secondary callbacks (header # and streaming_callback), as errors there must be seen as errors # by the http client so it can clean up the connection. exc_info = [] def handle_callback_exception(callback): exc_info.append(sys.exc_info()) self.stop() self.io_loop.handle_callback_exception = handle_callback_exception with NullContext(): self.http_client.fetch(self.get_url('/hello'), lambda response: 1 / 0) self.wait() self.assertEqual(exc_info[0][0], ZeroDivisionError)
def addWriter(self, writer): """ Add a FileDescriptor for notification of data available to write. """ if writer in self._writers: return self._writers[writer] = True fd = writer.fileno() if fd in self._fds: (reader, _) = self._fds[fd] self._fds[fd] = (reader, writer) if reader: # We already registered this fd for read events, # update it for write events as well. self._ioloop.update_handler(fd, IOLoop.READ | IOLoop.WRITE) else: with NullContext(): self._fds[fd] = (None, writer) self._ioloop.add_handler(fd, self._invoke_callback, IOLoop.WRITE)
def queue_push(self, device_token, payload): """ 时序内部对msg_id做映射,仅v1&v2协议格式支持错误应答 :param device_token: 设备apns token :param payload: 包文dict """ with NullContext(): #多次对象拷贝 legacy_buffers = None if self.__conn is None else self.__conn.sending_buffer[:] if self.__conn is None or self.__conn.critical: #不判定connected状态,因为该函数调用过快时,连接还未成功,导致前一个conn对象直接被gc回收 #critical变量只有在read异常时设置 self.__conn = _APNConn(legacy_buffers, *self.__conf) logger.debug('new conn: %x' % id(self.__conn)) IOLoop.instance().add_timeout( timedelta(seconds=RENEW_CONN_TS), partial(clear_connection, self.__conn)) self.__conn.connect() self.__conn.append(device_token, payload)
def addReader(self, reader): """ Add a FileDescriptor for notification of data available to read. """ if reader in self._readers: # Don't add the reader if it's already there return self._readers[reader] = True fd = reader.fileno() if fd in self._fds: (_, writer) = self._fds[fd] self._fds[fd] = (reader, writer) if writer: # We already registered this fd for write events, # update it for read events as well. self._io_loop.update_handler(fd, IOLoop.READ | IOLoop.WRITE) else: with NullContext(): self._fds[fd] = (reader, None) self._io_loop.add_handler(fd, self._invoke_callback, IOLoop.READ)
def wait(self, condition=None, timeout=5): """Runs the IOLoop until stop is called or timeout has passed. In the event of a timeout, an exception will be thrown. If condition is not None, the IOLoop will be restarted after stop() until condition() returns true. """ if not self.__stopped: if timeout: def timeout_func(): try: raise self.failureException( 'Async operation timed out after %s seconds' % timeout) except Exception: self.__failure = sys.exc_info() self.stop() if self.__timeout is not None: self.io_loop.remove_timeout(self.__timeout) self.__timeout = self.io_loop.add_timeout( datetime.timedelta(seconds=timeout), timeout_func) while True: self.__running = True with NullContext(): # Wipe out the StackContext that was established in # self.run() so that all callbacks executed inside the # IOLoop will re-run it. self.io_loop.start() if (self.__failure is not None or condition is None or condition()): break assert self.__stopped self.__stopped = False self.__rethrow() result = self.__stop_args self.__stop_args = None return result
def gcall(f, *args, **kwargs): ''' Calls a function, makes it asynchronous, and returns the result of the function as a :class:`tornado.concurrent.Future`. The wrapped function may use :func:`gyield` to pseudo-synchronously wait for a future to resolve. This is the same code that :func:`@greenado.groutine <groutine>` uses to wrap functions. :param f: Function to call :param args: Function arguments :param kwargs: Function keyword arguments :returns: :class:`tornado.concurrent.Future` .. warning:: You should not discard the returned Future or exceptions may be silently discarded, similar to a tornado coroutine. See :func:`@gen.coroutine <tornado.gen.coroutine>` for details. ''' # When this function gets updated, update groutine.wrapper also! future = concurrent.TracebackFuture() def greenlet_base(): try: result = f(*args, **kwargs) except Exception: future.set_exc_info(sys.exc_info()) else: future.set_result(result) gr = greenlet.greenlet(sc_wrap(greenlet_base)) with NullContext(): gr.switch() return future
def invoke(self, *args, **kwargs): """异步调用redis相关接口 :param args: 多条redis指令 :param kwargs: 用于设置事务开关等 """ #如不包含事务参数,则默认开启;否则按设置执行 active_trans = kwargs.get('active_trans') if active_trans is None: active_trans = True write_buf = _chain_cmds(active_trans, *args) future = TracebackFuture() def handle_resp(resp): f = resp.get(_RESP_FUTURE) or future err = resp.get(RESP_ERR) result = resp.get(RESP_RESULT) if err: f.set_exception(err) else: f.set_result(result) with NullContext(): if self.__conn is None: self.__conn = _RedisConnection(self.__io_loop, write_buf, handle_resp, self.__redis_tuple, self.__pwd) if self.__conn.connect_state() == CONNECT_INIT: self.__conn.connect(future, self.__redis_tuple, active_trans, len(args)) else: self.__conn.write(write_buf, future, False, active_trans, len(args)) return future
if __name__ == '__main__': from tornado.wsgi import WSGIContainer from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop from tornado.web import RequestHandler, Application from tornado.stack_context import NullContext from codeMarble_Web import create_app from codeMarble_Web.codeMarble_propertyParser import configs, propertyParser propertyParser() reload(sys).setdefaultencoding('utf-8') application = create_app() http_server = HTTPServer(WSGIContainer(application)) try: path, _ = os.path.split(os.path.abspath(__file__)) os.mkdir(os.path.join(path, 'problemData')) except Exception as e: pass with NullContext(): http_server.bind(int(configs['webPort'])) http_server.start(int(configs['processCount'])) IOLoop.instance().start()
def gyield(future, timeout=None): ''' This is functionally equivalent to the 'yield' statements used in a :func:`@gen.coroutine <tornado.gen.coroutine>`, but doesn't require turning all your functions into generators -- so you can use the return statement normally, and exceptions won't be accidentally discarded. This can be used on any function that returns a future object, such as functions decorated by :func:`@gen.coroutine <tornado.gen.coroutine>`, and most of the tornado API as of tornado 4.0. This function must only be used by functions that either have a :func:`@greenado.groutine <groutine>` decorator, or functions that are children of functions that have the decorator applied. :param future: A :class:`tornado.concurrent.Future` object :param timeout: Number of seconds to wait before raising a :exc:`TimeoutError`. Default is no timeout. `Parameter added in version 0.1.8.` :returns: The result set on the future object :raises: * If an exception is set on the future, the exception will be thrown to the caller of gyield. * If the timeout expires, :exc:`TimeoutError` will be raised. .. versionchanged:: 0.1.8 Added timeout parameter .. versionchanged:: 0.2.0 If a timeout occurs, the :exc:`TimeoutError` will not be set on the future object, but will only be raised to the caller. .. note: This cannot be used with :func:`tornado.gen.moment`, use :func:`gmoment` instead ''' gr = greenlet.getcurrent() assert gr.parent is not None, "gyield() can only be called from functions that have the @greenado.groutine decorator in the call stack." # don't switch/wait if the future is already ready to go if not future.done(): io_loop = IOLoop.current() wait_future = future if timeout != None and timeout > 0: # optimization: only do timeout related work if a timeout is happening.. timeout_handle = None timeout_future = None def on_complete(result): if timeout_future.done(): # resolve the future so tornado doesn't complain try: result.result() except Exception: # If you don't want to see this error, then implement cancellation # in the thing that the future came from logger.warn( "gyield() timeout expired, and this exception was ignored", exc_info=1) else: timeout_future.set_result(True) io_loop.remove_timeout(timeout_handle) gr.switch() def on_timeout(): timeout_future.set_exception( TimeoutError("Timeout after %s seconds" % timeout)) gr.switch() wait_future = timeout_future = concurrent.TracebackFuture() timeout_handle = io_loop.add_timeout(io_loop.time() + timeout, on_timeout) else: def on_complete(result): gr.switch() io_loop.add_future(future, on_complete) with NullContext(): gr.parent.switch() while not wait_future.done(): gr.parent.switch() wait_future.result() return future.result()
def f1(): with NullContext(): wrapped = wrap(f2) with StackContext(functools.partial(self.context, 'c2')): wrapped()