当前位置: 首页>>代码示例>>Python>>正文


Python BlockingConnection.close方法代码示例

本文整理汇总了Python中pika.adapters.BlockingConnection.close方法的典型用法代码示例。如果您正苦于以下问题:Python BlockingConnection.close方法的具体用法?Python BlockingConnection.close怎么用?Python BlockingConnection.close使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在pika.adapters.BlockingConnection的用法示例。


在下文中一共展示了BlockingConnection.close方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。

示例1: RabbitMQProcessor

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
class RabbitMQProcessor(CrawlQueue):
    """class created to encapsulate the rabbit reading and rewriting proccess
    to make common interface towards already existing crawle code
    Author: Maximiliano Mendez
    """

    def __init__(self, host, queue_name):
        super(RabbitMQProcessor, self).__init__()
        self.queue_name = queue_name
        self.parameters = pika.ConnectionParameters(host)
        self.connection = BlockingConnection(self.parameters)

        self.channel = self.connection.channel()
        self.channel.queue_declare(queue=self.queue_name, durable=True, exclusive=False, auto_delete=False)

    def _get(self):
        method, header, body = self.channel.basic_get(queue=self.queue_name)

        if method.NAME == "Basic.GetEmpty":
            raise Queue.Empty
        req_res = pickle.loads(body)
        self.channel.basic_ack(delivery_tag=method.delivery_tag)
        return req_res

    def _put(self, req_res):
        message = pickle.dumps(req_res)
        self.channel.basic_publish(
            exchange="",
            routing_key=self.queue_name,
            body=message,
            properties=pika.BasicProperties(content_type="text/plain", delivery_mode=1),
        )

    def stop(self):
        self.connection.close()
开发者ID:popego,项目名称:fetcher,代码行数:37,代码来源:crawle.py

示例2: main

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
def main(argv=None):
    """Main logic hit by the commandline invocation."""
    parser = argparse.ArgumentParser(__doc__)
    parser.add_argument('config', help="path to the configuration file")
    args = parser.parse_args(argv)
    if args.config is not None:
        fileConfig(args.config)
        logger.info("Logging initialized")

    config = ConfigParser()
    config.read(args.config)
    # Grab the database uri setting from the config.
    Session = create_database_session(config.get('anomaly', 'database-uri'))

    # Queue initialization
    connection = BlockingConnection()
    channel = connection.channel()
    # Declare the exchange and an unnamed queue.
    channel.exchange_declare(exchange=EXCHANGE, type='topic')
    declared_queue = channel.queue_declare(queue=QUEUE, durable=True,
                                           exclusive=False)
    channel.queue_bind(exchange=EXCHANGE, queue=QUEUE,
                       routing_key=BINDING_KEY)

    # Setup up our consumer callback
    channel.basic_consume(consumer, queue=QUEUE)

    try:
        channel.start_consuming()
    except KeyboardInterrupt:
        channel.stop_consuming()
    connection.close()
开发者ID:pumazi,项目名称:anomaly,代码行数:34,代码来源:catchall.py

示例3: test_blocking_send_get

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
def test_blocking_send_get():

    parameters = pika.ConnectionParameters(host=HOST, port=PORT)
    connection = BlockingConnection(parameters)

    # Open the channel
    channel = connection.channel()

    # Declare the queue
    queue_name = support.tools.test_queue_name('blocking_send_get')
    channel.queue_declare(queue=queue_name,
                          durable=False,
                          exclusive=True,
                          auto_delete=True)

    message = 'test_blocking_send:%.4f' % time.time()
    channel.basic_publish(exchange='',
                          routing_key=queue_name,
                          body=message,
                          properties=pika.BasicProperties(
                            content_type="text/plain",
                            delivery_mode=1))

    # Loop while we try to get the message we sent
    message_in = channel.basic_get(queue=queue_name)

    # Close the connection
    connection.close()

    # Only check the body
    if message_in[2] != message:
        assert False, "Did not receive the same message back"
开发者ID:bkjones,项目名称:pika,代码行数:34,代码来源:blocking_send_get_test.py

示例4: test_blocking_send_get

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
def test_blocking_send_get():

    connection = BlockingConnection(support.PARAMETERS)

    # Open the channel
    channel = connection.channel()

    # Declare the queue
    queue_name = support.tools.test_queue_name('blocking_send_get')
    channel.queue_declare(queue=queue_name,
                          durable=False,
                          exclusive=True,
                          auto_delete=True)

    message = ('test_blocking_send:%.4f' % time()).encode('utf-8')
    channel.basic_publish(routing_key=queue_name,
                          exchange="",
                          body=message,
                          properties=BasicProperties(
                                  content_type="text/plain",
                                  delivery_mode=1))

    # Loop while we try to get the message we sent
    message_in = channel.basic_get(queue=queue_name)

    # Close the connection
    connection.close()

    # Only check the body
    if message_in[2] != message:
        assert False, "Did not receive the same message back"
开发者ID:Kozea,项目名称:pika,代码行数:33,代码来源:blocking_send_get_test.py

示例5: main

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
def main(argv=None):
    """Main logic hit by the commandline invocation."""
    parser = argparse.ArgumentParser(__doc__)
    parser.add_argument("config", help="path to the configuration file")
    parser.add_argument("-n", "--name", help="drone name (used in configuration)")
    args = parser.parse_args(argv)
    if args.config is not None:
        fileConfig(args.config)
        logger.info("Logging initialized")

    config = ConfigParser()
    config.read(args.config)

    # Retrieve the drone's settings from a generic section or one
    #   specified in the arguments.
    config_section = "drone"
    if args.name is not None:
        config_section = "drone:{0}".format(args.name)
    drone_settings = dict(config.items(config_section))

    # XXX Used to initialize a sql session, but this should never
    #     happen because drones shouldn't have access to the
    #     persistent storage.
    Session = create_database_session(config.get("anomaly", "database-uri"))

    # Queue initialization
    connection = BlockingConnection()
    channel = connection.channel()
    # Declare the exchange and an unnamed queue.
    channel.exchange_declare(exchange=EXCHANGE, type="topic")
    declared_queue = channel.queue_declare(exclusive=True)
    queue_name = declared_queue.method.queue
    channel.queue_bind(exchange=EXCHANGE, queue=queue_name, routing_key=drone_settings["binding-key"])

    # Import the consumer from the settings line.
    module_path, consumer_name = drone_settings["consumer-class"].split(":")
    consumer_import = __import__(module_path, globals(), locals(), [consumer_name])
    consumer_cls = getattr(consumer_import, consumer_name)
    consumer = consumer_cls(drone_settings)

    # Setup up our consumer callback
    channel.basic_consume(consumer, queue=queue_name)

    try:
        channel.start_consuming()
    except KeyboardInterrupt:
        channel.stop_consuming()
    connection.close()
开发者ID:pumazi,项目名称:anomaly,代码行数:50,代码来源:drone.py

示例6: emit

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
    def emit(self, record):
        msg = self.format(record)

        body = json.dumps(
            {"msg": msg, "loggername": record.name, "level": record.levelname, "created": datetime.now().isoformat()}
        )

        try:
            con = BlockingConnection(ConnectionParameters(self.host))
        except socket.error:
            raise RabbitConnectionException("Connection to {0} failed".format(self.host))
        channel = con.channel()

        channel.queue_declare(queue=self.queue, durable=True, exclusive=False, auto_delete=False)

        channel.basic_publish(exchange="", routing_key=self.queue, body=body)
        con.close()
开发者ID:hltbra,项目名称:rapidlog,代码行数:19,代码来源:rabbit.py

示例7: main

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
def main(argv=None):
    """Main logic hit by the commandline invocation."""
    logger.setLevel(logging.INFO)
    connection = BlockingConnection()
    channel = connection.channel()
    # Declare the exchange and an unnamed queue.
    channel.exchange_declare(exchange=EXCHANGE, type='topic')
    declared_queue = channel.queue_declare(exclusive=True)
    queue_name = declared_queue.method.queue
    channel.queue_bind(exchange=EXCHANGE, queue=queue_name,
                       routing_key=BINDING_KEY)

    # Setup up our consumer callback
    channel.basic_consume(consumer, queue=queue_name)

    try:
        channel.start_consuming()
    except KeyboardInterrupt:
        channel.stop_consuming()
    connection.close()
开发者ID:pumazi,项目名称:anomaly,代码行数:22,代码来源:example-consumer.py

示例8: __call__

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
    def __call__(self, consuming_channel, method, header, body):
        if header.content_type != 'application/json':
            raise Exception("unrecognized message content-type: "
                            "{0}".format(header.content_type))
        data = json.loads(body)

        # Create the SQL Job entry and commit it.
        type = data.get('type', '')
        persistent_job = PersistentJob(body, type)
        self.session.add(persistent_job)
        self.session.commit()
        id = persistent_job.id

        # Create the new Job message object.
        job = Job(id, data)
        job.stamp()
        logger.info("Created job {0}".format(job))

        # Submit the new message to the topic exchange.
        connection = BlockingConnection()
        channel = connection.channel()
        channel.exchange_declare(exchange=EXCHANGE, type='topic')

        routing_key = get_routing_key(job)
        message = jsonpickle.encode(job)
        properties = BasicProperties(content_type="application/json")
        channel.basic_publish(exchange=EXCHANGE,
                              routing_key=routing_key,
                              properties=properties,
                              body=message)
        logger.debug("Sent message to '{0}' with {1!r}".format(routing_key,
                                                               message))
        connection.close()

        # Acknowledge message receipt
        consuming_channel.basic_ack(method.delivery_tag)
开发者ID:pumazi,项目名称:anomaly,代码行数:38,代码来源:spotter.py

示例9: BlockingReader

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
class BlockingReader(object):
    def __init__(self, host, queue):

        self.queue = queue
        self.parameters = pika.ConnectionParameters(host)
        pika.log.info("Establishing connection")
        self.connection = BlockingConnection(self.parameters)

        pika.log.info("About to declare queue")

        pika.log.info("Queue declared")

    def read(self, channel):
        pika.log.info("Reading single message")
        method, header, body = channel.basic_get(queue=self.queue)
        pika.log.info("Message received!")
        channel.basic_ack(delivery_tag=method.delivery_tag)

    def create_channel(self):
        channel = self.connection.channel()
        return channel

    def stop(self):
        self.connection.close()
开发者ID:maximilianom,项目名称:fetcher,代码行数:26,代码来源:RabbitMQBlockingReaderTask.py

示例10: BasicProperties

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
            body = HTML_VALUE % random.randint(1, 32768)
            content_type = "text/html"
        elif msg_type == 2:
            body = JSON_VALUE % random.randint(1, 32768)
            content_type = "application/json"
        elif msg_type == 3:
            body = XML_VALUE % random.randint(1, 32768)
            content_type = "text/xml"
        elif msg_type == 4:
            body = YAML_VALUE % random.randint(1, 32768)
            content_type = "text/x-yaml"
        else:
            body = "Plain text value %i" % random.randint(1, 32768)
            content_type = "text/text"

        properties = BasicProperties(
            timestamp=int(time.time()),
            app_id=__file__,
            user_id="guest",
            content_type=content_type,
            message_id=str(uuid.uuid4()),
            type="Example message",
            reply_to="rejected_reply",
            delivery_mode=1,
        )

        # Send the message
        channel.basic_publish(exchange="example", routing_key="rejected_example", body=body, properties=properties)

    connection.close()
开发者ID:bdeeney,项目名称:rejected,代码行数:32,代码来源:test_generator.py

示例11: test_blocking_consume

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
def test_blocking_consume():

    parameters = pika.ConnectionParameters(host=HOST, port=PORT)
    connection = BlockingConnection(parameters)

    # Open the channel
    channel = connection.channel()

    # Declare the exchange
    exchange_name = support.tools.test_queue_name('blocking_exchange')
    frame = channel.exchange_declare(exchange=exchange_name,
                                     type="direct",
                                     auto_delete="true")
    if not isinstance(frame.method, pika.spec.Exchange.DeclareOk):
        assert False, \
        "Did not receive Exchange.DeclareOk from channel.exchange_declare"

    # Declare the queue
    queue_name = support.tools.test_queue_name('blocking_consume')
    frame = channel.queue_declare(queue=queue_name,
                                  durable=False,
                                  exclusive=True,
                                  auto_delete=True)

    if not isinstance(frame.method, pika.spec.Queue.DeclareOk):
        assert False, \
        "Did not receive Queue.DeclareOk from channel.queue_declare"

    routing_key = "%s.%s" % (exchange_name, queue_name)
    frame = channel.queue_bind(queue=queue_name,
                               exchange=exchange_name,
                               routing_key=routing_key)
    if not isinstance(frame.method, pika.spec.Queue.BindOk):
        assert False, \
        "Did not receive Queue.BindOk from channel.queue_bind"

    _sent = []
    _received = []

    @pika.log.method_call
    def _on_message(channel, method, header, body):
        _received.append(body)
        if len(_received) == MESSAGES:
            channel.stop_consuming()
        if start < time.time() - 2:
            assert False, "Test timed out"

    for x in xrange(0, MESSAGES):
        message = 'test_blocking_send:%i:%.4f' % (x, time.time())
        _sent.append(message)
        channel.basic_publish(exchange=exchange_name,
                              routing_key=routing_key,
                              body=message,
                              properties=pika.BasicProperties(
                                content_type="text/plain",
                                delivery_mode=1))

    # Loop while we get messages (for 2 seconds)
    start = time.time()

    # This is blocking
    channel.basic_consume(consumer=_on_message, queue=queue_name, no_ack=True)
    connection.close()

    # Check our results
    if len(_sent) != MESSAGES:
        assert False, "We did not send the expected qty of messages: %i" %\
                      len(_sent)
    if len(_received) != MESSAGES:
        assert False, "Did not receive the expected qty of messages: %i" %\
                      len(_received)
    for message in _received:
        if message not in _sent:
            assert False, 'Received a message we did not send.'
    for message in _sent:
        if message not in _received:
            assert False, 'Sent a message we did not receive.'
开发者ID:bkjones,项目名称:pika,代码行数:79,代码来源:blocking_consume_test.py

示例12: RabbitObj

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]

#.........这里部分代码省略.........
            raise TypeError("Queue must be a str, got %s instead" % \
                            str(type(queue_name)))
        self.queue_name = queue_name

        if isinstance(routing_key, unicode):
            routing_key = str(routing_key)
        elif not isinstance(routing_key, str):
            raise TypeError("Routing key must be a str, got %s instead" % \
                            str(type(queue_name)))
        self.routing_key = routing_key

        if DEBUG: print self._debug_prefix + "About to start connection...",

        # From here, determine how to initialize the connection further by 
        # what type of exchange was requested.
        if self.ex_type == "topic":
            self._init_topic_conn()
        #elif self.ex_type == "direct":
        #    self._init_direct_conn()
        elif not blocking:
            self._init_topic_conn()
        else:
            raise NotImplementedError("Only 'topic' and 'direct' exchange " \
                                      "types are currently supported.")


    def _init_topic_conn(self):
        self.connection = SelectConnection(self.conn_params, self.on_connected)
        try:
            # Loop so we can communicate with RabbitMQ
            self.connection.ioloop.start()
        except KeyboardInterrupt:
            # Gracefully close the connection
            self.connection.close()
            # Loop until we're fully closed, will stop on its own
            self.connection.ioloop.start()
        else:
            if DEBUG: print "Connection attempt rejected. Goodbye."


    def _init_direct_conn(self):
        blocking = True
        self.connection = BlockingConnection(self.conn_params)
        self.on_connected(self.connection, blocking)
        self.channel = self.connection.channel()
        self.on_channel_open(self.channel)


    def on_connected(self, connection, blocking=False):
        '''
        '''
        if DEBUG:
            print self._debug_prefix + "Connected\n  Host: %s\n  " \
                  "Exchange: %s\n" % (self.conn_params.host, self.exchange) + \
                  self._debug_prefix + "Creating channel...",
        # These should always be the same, but just in case...
        if self.connection is not connection:
            # Adopt the new connection object
            self.connection = connection
        if not blocking:
            self.connection.channel(on_open_callback=self.on_channel_open)


    def on_channel_open(self, new_channel):
        '''
        '''
开发者ID:mmabey,项目名称:bullitt,代码行数:70,代码来源:cuffrabbit.py

示例13:

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
rmq_channel.queue_declare(queue="pages", durable=True,
                          exclusive=False, auto_delete=False)

reader = csv.reader(open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'top-1m.csv'), 'rb'))

n = 1
for row in reader:
    if n < OFFSET:
      n += 1
      continue
    url = "http://%s" % row[1]
    command_data = {
        'run': RUN_NUMBER,
        'url': url,
        'fanout': FANOUT,
        'depth': DEPTH
        }
    print "[%2d] Adding page %s..." % (n, url),
    rmq_channel.basic_publish(exchange='',
                              routing_key="run%d" % RUN_NUMBER,
                              body=json.dumps(command_data),
                              properties=pika.BasicProperties(
            content_type="text/plain",
            delivery_mode=1))
    print "Delivered"
    n += 1
    if n > NUM_SITES + OFFSET:
        break

rmq_connection.close()
开发者ID:wli,项目名称:phantom-measurement,代码行数:32,代码来源:initialize_queue.py

示例14: Queue

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
class Queue(object):
    """
    A class for performing both sends and receives on a RabbitMQ server,
    using the pika library.
    """

    def __init__(self):
        self.declared_channels = []
        self.logger = getLogger(__name__)


    def set_logger(self, logger):
        self.logger = logger


    def declare_exchange(self, exchange_name, queue_options,  exchange_type="topic"):
        try:
            self.channel.exchange_declare(exchange=exchange_name, type=exchange_type, **queue_options)
        except AMQPChannelError:
            pass


    def bind_queue(self, exchange, queue_name, routing_key=None):
        kwargs = dict(
            exchange=exchange, queue=queue_name
        )
        if routing_key is not None:
            kwargs['routing_key'] = routing_key

        bind = self.channel.queue_bind(**kwargs)

    def connect(self, connection_params):
        """
        Performs the actual connection to the RabbitMQ server.

        :param connection_params: The connection parameters. See pika.ConnectionParameters for available properties
        :type connection_params: dict
        """
        connect_params_obj = ConnectionParameters(**connection_params)
        self.connection = BlockingConnection(connect_params_obj)
        self.channel = self.connection.channel()


    def declare_queue(self, queue_name=None, queue_options={}):
        """
        Declares a queue on the server. A list of declared is kept so we do not
        redeclare an existing queue.

        :param queue: Name of the queue to declare
        :type queue: string
        :param queue_options: Options for the queue, for details see pika.spec.DriverMixin.queue_declare
        :type queue_options: dict
        """

        queue_params = queue_options.copy()

        if queue_name not in self.declared_channels:
            if queue_name is not None:
                queue_params['queue'] = queue_name
            queue = self.channel.queue_declare(**queue_params)

            if queue_name is None:
                queue_name = queue.method.queue

            self.declared_channels.append(queue_name)
        return queue_name

    def disconnect(self):
        """
        Drop the connection to the RabbitMQ server
        """
        self.connection.close()

    def send(self, exchange_name, routing_key, body, exchange_type="topic"):
        """
        Put a message into the specified queue

        :param exchange_name: The name of the exchange to use
        :type exchange_name: str
        :param routing_key: The routing key to be used for this message
        :type routing_key: str
        :param body: The actual message body
        :type body: str
        :param exchange_type: Which type of exchange to use
        :type body: str
        """

        if not isinstance(body, str):
            body = json.dumps(body)

        try:
            self.channel
        except NameError:
            self.logger.error("You must connect first!")

        self.channel.basic_publish(exchange=exchange_name,
                                   routing_key=routing_key,
                                   body=body,
                                   properties=BasicProperties(content_type="text/plain", delivery_mode=2)
        )
#.........这里部分代码省略.........
开发者ID:Tilley,项目名称:pika_simple_daemon,代码行数:103,代码来源:queue.py

示例15: test_blocking_consume

# 需要导入模块: from pika.adapters import BlockingConnection [as 别名]
# 或者: from pika.adapters.BlockingConnection import close [as 别名]
def test_blocking_consume():

    # Connect to RabbitMQ
    connection = BlockingConnection(support.PARAMETERS)

    # Open the channel
    channel = connection.channel()

    # Declare the exchange
    exchange_name = support.tools.test_queue_name("blocking_exchange")
    frame = channel.exchange_declare(exchange=exchange_name, type="direct", auto_delete=True)
    if not isinstance(frame.method, Exchange.DeclareOk):
        assert False, "Did not receive Exchange.DeclareOk from channel.exchange_declare"

    # Declare the queue
    queue_name = support.tools.test_queue_name("blocking_consume")
    frame = channel.queue_declare(queue=queue_name, durable=False, exclusive=True, auto_delete=True)

    if not isinstance(frame.method, Queue.DeclareOk):
        assert False, "Did not receive Queue.DeclareOk from channel.queue_declare"

    routing_key = "%s.%s" % (exchange_name, queue_name)
    frame = channel.queue_bind(queue=queue_name, exchange=exchange_name, routing_key=routing_key)
    if not isinstance(frame.method, Queue.BindOk):
        assert False, "Did not receive Queue.BindOk from channel.queue_bind"

    _sent = []
    _received = []

    def _on_message(channel, method, header, body):
        _received.append(body)
        if len(_received) == MESSAGES:
            channel.stop_consuming()
        if start < time() - MAX_DURATION:
            assert False, "Test timed out"

    for x in xrange(0, MESSAGES):
        message = "test_blocking_send:%i:%.4f" % (x, time())
        _sent.append(message)
        channel.basic_publish(
            exchange=exchange_name,
            routing_key=routing_key,
            body=message,
            properties=BasicProperties(content_type="text/plain", delivery_mode=1),
        )

    # Loop while we get messages (for 2 seconds)
    start = time()

    # This is blocking
    channel.basic_consume(consumer_callback=_on_message, queue=queue_name, no_ack=True)
    channel.start_consuming()
    connection.close()

    # Check our results
    if len(_sent) != MESSAGES:
        assert False, "We did not send the expected qty of messages: %i" % len(_sent)
    if len(_received) != MESSAGES:
        assert False, "Did not receive the expected qty of messages: %i" % len(_received)
    for message in _received:
        if message not in _sent:
            assert False, "Received a message we did not send."
    for message in _sent:
        if message not in _received:
            assert False, "Sent a message we did not receive."
开发者ID:nexiles,项目名称:pika,代码行数:67,代码来源:blocking_consume_test.py


注:本文中的pika.adapters.BlockingConnection.close方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。