Пример #1
0
 async def __call_sync(self,
                       task,
                       outputs,
                       idx,
                       limiter,
                       max_retries=1,
                       pass_fail_job=False):
     if limiter is not None:
         async with limiter:
             for retry_idx in range(max_retries):
                 try:
                     outputs[idx] = task()
                     self.update_progress_bar()
                     return None
                 except Exception:
                     if retry_idx == max_retries - 1 and not pass_fail_job:
                         with except_handler():
                             raise AssertionError(
                                 "ERROR in {}th task.\n {1}".format(
                                     idx,
                                     format_exc(
                                         name="mlchain.workflows.parallel")
                                 ))
                     if retry_idx < max_retries - 1 or not self.verbose:
                         logger.error(
                             "PARALLEL ERROR in {0}th task and retry task,"
                             " run times = {1}".format(idx, retry_idx + 1))
                     else:
                         logger.debug(
                             "PASSED PARALLEL ERROR in {}th task:".format(
                                 idx,
                                 format_exc(
                                     name="mlchain.workflows.parallel")))
     else:
         for retry_idx in range(max_retries):
             try:
                 outputs[idx] = task()
                 self.update_progress_bar()
                 return None
             except Exception:
                 if retry_idx == max_retries - 1 and not pass_fail_job:
                     with except_handler():
                         raise AssertionError("ERROR in {}th task\n".format(
                             idx,
                             format_exc(name="mlchain.workflows.parallel")))
                 if retry_idx < max_retries - 1 or not self.verbose:
                     logger.error(
                         "PARALLEL ERROR in {0}th task and retry task,"
                         " run times = {1}".format(idx, retry_idx + 1))
                 else:
                     logger.debug("PASSED PARALLEL ERROR: {0}".format(
                         format_exc(name="mlchain.workflows.parallel")))
     self.update_progress_bar()
Пример #2
0
 def exec_task(self, task, idx=None):
     for retry_idx in range(self.max_retries):
         try:
             output = task.exec()
             self.update_progress_bar()
             return output
         except Exception as ex:
             if retry_idx == self.max_retries - 1 and not self.pass_fail_job:
                 return ex
             if retry_idx < self.max_retries - 1 or not self.verbose:
                 logger.error(
                     "PARALLEL ERROR in {0}th task and retry task, "
                     "run times = {1}".format(idx, retry_idx + 1))
             else:
                 logger.debug("PASSED PARALLEL ERROR in {}th task:".format(
                     idx, format_exc(name="mlchain.workflows.parallel")))
     return None
Пример #3
0
 def download_bytes(self, key, bucket_name=None, use_basename=True):
     """
     Download a file from S3.
     Args:
         key: `str`. S3 key that will point to the file.
         local_path: `str`. the path to download to.
         bucket_name: `str`. Name of the bucket in which to store the file.
         use_basename: `bool`. whether or not to use the basename of the key.
     """
     if not bucket_name:
         bucket_name = self.bucket
     try:
         f = BytesIO()
         self.client.download_fileobj(bucket_name, key, f)
         return f.getvalue()
     except Exception as e:
         logger.error(str(e))
         return None
Пример #4
0
    def call(self, request, context):
        header = request.header
        function_name = request.function_name
        args = request.args
        kwargs = request.kwargs
        serializer = self.get_serializer(header.serializer)
        headers = request.headers
        uid = str(uuid4())
        mlchain_context.set(headers)
        mlchain_context['MLCHAIN_CONTEXT_ID'] = uid
        args = serializer.decode(args)
        kwargs = serializer.decode(kwargs)
        func = self.model.get_function(function_name)
        kwargs = self.get_kwargs(func, *args, **kwargs)
        kwargs = self._normalize_kwargs_to_valid_format(kwargs, func)
        try:
            start = time.time()
            output = self.model.call_function(function_name, None, **kwargs)
            duration = time.time() - start
            output = {
                'output': output,
                'time': duration,
                'api_version': self.version,
                'mlchain_version': mlchain.__version__
            }
        except MlChainError as ex:
            err = ex.msg
            logger.error("code: {0} msg: {1}".format(ex.code, ex.msg))
            output = {
                'error': err,
                'time': 0,
                'code': ex.code,
                'api_version': self.version,
                'mlchain_version': mlchain.__version__
            }

        except Exception as ex:
            output = {
                'output': str(ex),
                'time': 0,
                'api_version': self.version,
                'mlchain_version': mlchain.__version__
            }
        return mlchain_pb2.Output(output=serializer.encode(output))
Пример #5
0
 def download_cv2(self, key, bucket_name=None):
     """
     Download a file from S3.
     Args:
         key: `str`. S3 key that will point to the file.
         local_path: `str`. the path to download to.
         bucket_name: `str`. Name of the bucket in which to store the file.
         use_basename: `bool`. whether or not to use the basename of the key.
     """
     if not bucket_name:
         bucket_name = self.bucket
     try:
         f = BytesIO()
         self.client.download_fileobj(bucket_name, key, f)
         cv2 = import_cv2()
         return cv2.imdecode(
             np.asarray(bytearray(f.getvalue()), dtype="uint8"),
             cv2.IMREAD_COLOR)
     except Exception as e:
         logger.error(str(e))
         return None
Пример #6
0
 def download_file(self,
                   key,
                   local_path,
                   bucket_name=None,
                   use_basename=False):
     """
     Download a file from S3.
     Args:
         key: `str`. S3 key that will point to the file.
         local_path: `str`. the path to download to.
         bucket_name: `str`. Name of the bucket in which to store the file.
         use_basename: `bool`. whether or not to use the basename of the key.
     """
     if not bucket_name:
         bucket_name = self.bucket
     local_path = os.path.abspath(local_path)
     if use_basename:
         local_path = os.path.join(
             local_path,
             os.path.basename(key))  # append_basename(local_path, key)
     dir_name = os.path.dirname(local_path)
     if not os.path.exists(dir_name):
         os.makedirs(dir_name)
     try:
         self.client.download_file(
             bucket_name,
             key,
             local_path,
             Callback=ProgressPercentage(
                 key,
                 self.client.head_object(Bucket=bucket_name,
                                         Key=key)["ContentLength"]))
         return True
     except Exception as e:
         logger.error(str(e))
         return False
Пример #7
0
def exception_handle(type, value, traceback):
    logger.error(format_exc(tb=traceback, exception=value))
Пример #8
0
    def run(self, host='127.0.0.1', port=8080, bind=None, cors=False, cors_resources={},
            cors_allow_origins='*', gunicorn=False, debug=False,
            use_reloader=False, workers=1, timeout=60, keepalive=10,
            max_requests=0, threads=1, worker_class='gthread', umask='0',
            ngrok=False, model_id=None, **kwargs):
        """
        Run a server from a Python class
        :model: Your model class
        :host: IP address you want to start server
        :port: Port to start server at
        :bind: Gunicorn: The socket to bind. A list of string or string of the form: HOST, HOST:PORT, unix:PATH, fd://FD. An IP is a valid HOST.
        :deny_all_function: Default is False, which enable all function except function with @except_serving or function in blacklist, True is deny all and you could use with whitelist
        :blacklist: All listing function name here won't be served
        :whitelist: Served all function name inside whitelist
        :cors: Enable CORS or not
        :cors_resources: Config Resources of flask-cors
        :cors_allow_origins: Allow host of cors
        :gunicorn: Run with Gunicorn or not
        :debug: Debug or not
        :use_reloader: Default False, which is using 1 worker in debug instead of 2
        :workers: Number of workers to run Gunicorn
        :timeout: Timeout of each request
        :keepalive: The number of seconds to wait for requests on a Keep-Alive connection.
        :threads: The number of worker threads for handling requests. Be careful, threads would break your result if it is bigger than 1
        :worker_class: The type of workers to use.
        :max_requests: Max Request to restart Gunicorn Server, default is 0 which means no restart
        :umask: A bit mask for the file mode on files written by Gunicorn.
        :kwargs: Other Gunicorn options
        """
        try:
            self.register_swagger()
        except Exception as ex:
            logger.error("Can't register swagger with error {0}".format(ex))

        if ngrok:
            from pyngrok import ngrok as pyngrok
            endpoint = pyngrok.connect(port=port)
            logger.info("Ngrok url: {0}".format(endpoint))
            os.environ['NGROK_URL'] = endpoint
        else:
            endpoint = os.environ.get('NGROK_URL')

        try:
            register_autofrontend(model_id=model_id, serve_model=self.model,
                                  version=self.version,
                                  endpoint=endpoint)
        except Exception as ex:
            logger.error("Can't register autofrontend with error {0}".format(ex))

        if cors:
            CORS(self.app, resources=cors_resources, origins=cors_allow_origins)
        
        if not gunicorn:
            if bind is not None:
                if isinstance(bind, str):
                    bind = [bind]
                if isinstance(bind, list):
                    for ip_port in bind:
                        if re.match(r'(localhost:|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|:)){4})\d+', ip_port):
                            logger.warning("Using host and port in bind to runserver")
                            host, port = ip_port.split(":")

            logger.info("-" * 80)
            logger.info("Served model with Flask at host={0}, port={1}".format(host, port))
            logger.info("Debug = {}".format(debug))
            logger.info("-" * 80)

            self.app.run(host=host, port=port, debug=debug,
                         use_reloader=use_reloader, threaded=threads > 1)
        else:
            # Process bind, host, port
            if isinstance(bind, str):
                bind = [bind]

            bind_host_port = '%s:%s' % (host, port)
            if bind is None:
                bind = [bind_host_port]

            logger.info("-" * 80)
            logger.info("Served model with Flask and Gunicorn at bind={}".format(bind))
            logger.info("Number of workers: {}".format(workers))
            logger.info("Number of threads: {}".format(threads))
            logger.info("API timeout: {}".format(timeout))
            logger.info("Debug = {}".format(debug))
            logger.info("-" * 80)

            loglevel = kwargs.get('loglevel', 'warning' if debug else 'info')
            
            GunicornWrapper(self.app, bind=bind, workers=workers, timeout=timeout,
                            keepalive=keepalive, max_requests=max_requests,
                            loglevel=loglevel, worker_class=worker_class,
                            threads=threads, umask=umask, **kwargs).run()