欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

rabbitmq(中間消息代理)在python中的使用詳解

 更新時(shí)間:2017年12月14日 09:57:18   作者:碼農(nóng)47  
這篇文章主要介紹了rabbitmq(中間消息代理)在python中的使用詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

在之前的有關(guān)線程,進(jìn)程的博客中,我們介紹了它們各自在同一個(gè)程序中的通信方法。但是不同程序,甚至不同編程語言所寫的應(yīng)用軟件之間的通信,以前所介紹的線程、進(jìn)程隊(duì)列便不再適用了;此種情況便只能使用socket編程了,然而不同程序之間的通信便不再像線程進(jìn)程之間的那么簡單了,要考慮多種情況(比如其中一方斷線另一方如何處理;消息群發(fā),多個(gè)程序之間的通信等等),如果每遇到一次程序間的通信,便要根據(jù)不同情況編寫不同的socket,還要維護(hù)、完善這個(gè)socket這會(huì)使得編程人員的工作量大大增加,也使得程序更易崩潰。所以,一般遇到這種情況,便使用消息隊(duì)列MQ(Message Queue),那么問題來了。

1. 什么是消息隊(duì)列MQ?

MQ是一種應(yīng)用程序?qū)?yīng)用程序的通信方法。應(yīng)用程序通過讀出(寫入)隊(duì)列的消息(針對(duì)應(yīng)用程序的數(shù)據(jù))來通信,而無需使用專用連接來鏈接它們。消息傳遞指的是程序之間通過在消息中發(fā)送數(shù)據(jù)進(jìn)行通信,而不是通過直接調(diào)用彼此來通信,排隊(duì)指的是應(yīng)用程序通過 隊(duì)列來通信。隊(duì)列的使用排除了接收和發(fā)送應(yīng)用程序同時(shí)執(zhí)行的要求。

2. 什么是rabbitmq?如何使用它?

RabbitMQ是流行的開源消息隊(duì)列系統(tǒng),用erlang語言開發(fā)。RabbitMQ是AMQP(高級(jí)消息隊(duì)列協(xié)議)的標(biāo)準(zhǔn)實(shí)現(xiàn)。

RabbitMQ也是前面所提到的生產(chǎn)者消費(fèi)者模型,一端發(fā)送消息(生產(chǎn)任務(wù)),一端接收消息(處理任務(wù))。

rabbitmq的詳細(xì)使用(包括各種系統(tǒng)的安裝配置)可參見其官方文檔:http://www.rabbitmq.com/documentation.html

由于應(yīng)用程序之間的通信情況異常復(fù)雜,rabbitmq支持的編程語言有10多種,所以在此博客中不可能完全演示rabbitmq的所有使用。本片博客將會(huì)介紹rabbitmq在python中的基本使用,如果你只想使用rabbitmq完成一些簡單的任務(wù),則本篇博客足以滿足你的需求;如果你想深入學(xué)習(xí)了解rabbitmq的工作原理,那么讀完本篇博客,你可以更容易的讀懂rabbitmq的官方文檔;當(dāng)然這些只限于你在使用python編程。

在python中我們使用pika(第三方模塊,使用pip安裝即可使用)模塊進(jìn)行rabbitmq的操作,接下來,使用python實(shí)現(xiàn)一個(gè)rabbitmq最簡單的通信。

In the diagram below, "P" is our producer and "C" is our consumer. The box in the middle is a queue - a message buffer that RabbitMQ keeps on behalf of the consumer.

Our overall design will look like:

Producer sends messages to the "hello" queue. The consumer receives messages from that queue.

例一(簡單的消息收發(fā)):

Sending

Our first programsend.pywill send a single message to the queue. The first thing we need to do is to establish a connection with RabbitMQ server.

import pika
connection = pika.BlockingConnection(pika.ConnectionParameters("localhost")) # 建立程序與rabbitmq的連接
channel = connection.channel()
channel.queue_declare(queue='hello') # 定義hello隊(duì)列
channel.basic_publish(exchange='',
      routing_key='hello', # 告訴rabbitmq將消息發(fā)送到hello隊(duì)列中
      body='Hello world!') # 發(fā)送消息的內(nèi)容
print(" [x] Sent 'Hello World!'")
connection.close() # 關(guān)閉與rabbitmq的連接

Our second programreceive.pywill receive messages from the queue and print them on the screen.

import pika
import time
connection = pika.BlockingConnection(pika.ConnectionParameters("localhost")) # 建立程序與rabbitmq的連接
channel = connection.channel()
# 在接收端定義隊(duì)列,參數(shù)與發(fā)送端的相同
channel.queue_declare(queue='hello')
def callback(ch, method, properties, body):
 """
 收到消息調(diào)用callback處理消息
 :param ch:
 :param method:
 :param properties:
 :param body:
 :return:
 """
 print(" [x] received %r" % body)
 # time.sleep(30)
 print("Done....")
channel.basic_consume(callback,
      queue='hello', # 告訴rabbitmq此程序從hello隊(duì)列中接收消息
      no_ack=True)

# channel.basic_consume(callback,
#      queue='hello')
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming() # 開始接收,未收到消息阻塞

注1:我們可以打開time.sleep()的注釋(模仿任務(wù)處理所需的時(shí)間),將no_ack設(shè)為默認(rèn)值(不傳參數(shù)),同時(shí)運(yùn)行多個(gè)receive.py, 運(yùn)行send.py發(fā)一次消息,第一個(gè)開始運(yùn)行的receive.py接收到消息,開始處理任務(wù),如果中途宕機(jī)(任務(wù)未處理完);那么第二個(gè)開始運(yùn)行的receive.py就會(huì)接收到消息,開始處理任務(wù);如果第二個(gè)也宕機(jī)了,則第三個(gè)繼續(xù);如果依次所有運(yùn)行的receive都宕機(jī)(任務(wù)未處理完)了,則下次開始運(yùn)行的第一個(gè)receive.py將繼續(xù)接收消息處理任務(wù),這個(gè)機(jī)制防止了一些必須完成的任務(wù)由于處理任務(wù)的程序異常終止導(dǎo)致任務(wù)不能完成。如果將no_ack設(shè)為True,中途宕機(jī),則后面的接收端不會(huì)再接收消息處理任務(wù)。

注2:如果發(fā)送端不停的發(fā)消息,則接收端分別是第一個(gè)開始運(yùn)行的接收,第二個(gè)開始運(yùn)行的接收,第三個(gè)開始運(yùn)行接收,依次接收,這是rabbitmq的消息輪循機(jī)制(相當(dāng)于負(fù)載均衡,防止一個(gè)接收端接收過多任務(wù)卡死,當(dāng)然這種機(jī)制存在弊端,就是如果就收端機(jī)器有的配置高有的配置低,就會(huì)使配置高的機(jī)器得不到充分利用而配置低的機(jī)器一直在工作)。這一點(diǎn)可以啟動(dòng)多個(gè)receive.py,多次運(yùn)行send.py驗(yàn)證。

上面的例子我們介紹了消息的接收端(即任務(wù)的處理端)宕機(jī),我們?cè)撊绾翁幚?。接下來,我們將重點(diǎn)放在消息的發(fā)送端(即服務(wù)端),與接收端不同,如果發(fā)送端宕機(jī),則會(huì)丟失存儲(chǔ)消息的隊(duì)列,存儲(chǔ)的消息(要發(fā)送給接收端處理的任務(wù)),這些信息一旦丟失會(huì)造成巨大的損失,所以下面的重點(diǎn)就是消息的持久化,即發(fā)送端異常終止,重啟服務(wù)后,隊(duì)列,消息都將自動(dòng)加載進(jìn)服務(wù)里。其實(shí)只要將上面的代碼稍微修改就可實(shí)現(xiàn)。

例二(消息的持久化):

Sending:

import pika
connection = pika.BlockingConnection(pika.ConnectionParameters("localhost"))
channel = connection.channel()
channel.queue_declare(queue='task_queue', durable=True)  #使隊(duì)列持久化
message = "Hello World"
channel.basic_publish(exchange='',
      routing_key='task_queue',
      body=message,
      properties=pika.BasicProperties(
       delivery_mode=2,  #使消息持久化
      ))
print(" [x] Sent %r" % message)
connection.close()

Receiving:

import pika
import time

connection = pika.BlockingConnection(pika.ConnectionParameters("localhost"))
channel = connection.channel()

channel.queue_declare(queue='task_queue', durable=True) #再次申明隊(duì)列,和發(fā)送端參數(shù)應(yīng)一樣
print(' [*] Waiting for messages. To exit press CTRL+C')

def callback(ch, method, properties, body):
 print(" [x] received %r" % body)
 time.sleep(2)
 print(" [x] Done")
 # 因?yàn)闆]有設(shè)置no_ask=True, 所以需要告訴rabbitmq消息已經(jīng)處理完畢,rabbitmq將消息移出隊(duì)列。
 ch.basic_ack(delivery_tag=method.delivery_tag)

#同一時(shí)間worker只接收一條消息,等這條消息處理完在接收下一條
channel.basic_qos(prefetch_count=1)
channel.basic_consume(callback,
      queue='task_queue')


channel.start_consuming()

注1:worker.py中的代碼如果不設(shè)置,則new_task.py意外終止在重啟后,worker會(huì)同時(shí)接收終止前沒有處理的所有消息。兩個(gè)程序中的queue設(shè)置的參數(shù)要相同,否則程序出錯(cuò)。no_ask=True如果沒設(shè)置,則worker.py中的ch.basic_ack(delivery_tag=method.delivery_tag)這行代碼至關(guān)重要,如果不寫,則不管接收的消息有沒有處理完,此消息將一直存在與隊(duì)列中。

注2:這句代碼---channel.basic_qos(prefetch_count=1),解決了上例中消息輪循機(jī)制的代碼,即接收端(任務(wù)的處理端)每次只接收一個(gè)任務(wù)(參數(shù)為幾接收幾個(gè)任務(wù)),處理完成后通過向發(fā)送端的匯報(bào)(即注1中的代碼)來接收下一個(gè)任務(wù),如果有任務(wù)正在處理中它不再接收新的任務(wù)。

前面所介紹的例一,例二都是一條消息,只能被一個(gè)接收端收到。那么該如何實(shí)現(xiàn)一條消息多個(gè)接收端同時(shí)收到(即消息群發(fā)或著叫廣播模式)呢?

其實(shí),在rabbitmq中只有consumer(消費(fèi)者,即接收端)與queue綁定,對(duì)于producer(生產(chǎn)者,即發(fā)送端)只是將消息發(fā)送到特定的隊(duì)列。consumer從與自己相關(guān)的queue中讀取消息而已。所以要實(shí)現(xiàn)消息群發(fā),只需要將同一條放到多個(gè)消費(fèi)者隊(duì)列即可。在rabbitmq中這個(gè)工作由exchange來做,它可以設(shè)定三種類型,它們分別實(shí)現(xiàn)了不同的需求,我們分別來介紹。

例三(exchange的類型為fanout):

當(dāng)exchange的類型為fanout時(shí),所有綁定這個(gè)exchange的隊(duì)列都會(huì)收到發(fā)來的消息。

import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
# 申明一個(gè)exchange,兩個(gè)參數(shù)分別為exchange的名字和類型;當(dāng)exchang='fanout'時(shí),所有綁定到此exchange的消費(fèi)者隊(duì)列都將收到消息
channel.exchange_declare(exchange='logs',
       exchange_type='fanout')
# 消息可以在命令行啟動(dòng)腳本時(shí)以參數(shù)的形式傳入
# message = ' '.join(sys.argv[1:]) or "info: Hello World!"
message = 'Hello World!'
channel.basic_publish(exchange='logs',
      routing_key='',
      body=message)
print(" [x] Sent %r" % message)
connection.close()
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='logs',
       exchange_type='fanout')
# 隨機(jī)生成一個(gè)queue,此queue唯一,且在連接端開后自動(dòng)銷毀
result = channel.queue_declare(exclusive=True)
# 得到隨機(jī)生成消費(fèi)者隊(duì)列的名字
queue_name = result.method.queue
# 將消費(fèi)者隊(duì)列與exchange綁定
channel.queue_bind(exchange='logs',
     queue=queue_name)

print(' [*] Waiting for logs. To exit press CTRL+C')

def callback(ch, method, properties, body):
 print(" [x] received %r" % body)

channel.basic_consume(callback,
      queue=queue_name,
      no_ack=True)

channel.start_consuming()

注1:emit_log.py為消息的發(fā)送端,receive_logs.py為消息的接收端??梢酝瑫r(shí)運(yùn)行多個(gè)receive_logs.py,當(dāng)emit_log.py發(fā)送消息時(shí),可以發(fā)現(xiàn)所有正在運(yùn)行的receive_logs.py都會(huì)收到來自發(fā)送端的消息。

注2:類似與廣播,如果消息發(fā)送時(shí),接收端沒有運(yùn)行,那么它將不會(huì)收到此條消息,即消息的廣播是即時(shí)的。

例四(exchange的類型為direct):

當(dāng)exchange的類型為direct時(shí),發(fā)送端和接收端都要指明消息的級(jí)別,接收端只能接收到被指明級(jí)別的消息。

import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='direct_logs',
       exchange_type='direct')
# 命令行啟動(dòng)時(shí),以參數(shù)的的形式傳入發(fā)送消息的級(jí)別,未傳怎默認(rèn)設(shè)置未info
# severity = sys.argv[1] if len(sys.argv) > 2 else 'info'
# 命令行啟動(dòng)時(shí),以參數(shù)的的形式傳入發(fā)送消息的內(nèi)容,未傳怎默認(rèn)設(shè)置Hello World!
# message = ' '.join(sys.argv[2:]) or 'Hello World!'
# 演示使用,實(shí)際運(yùn)用應(yīng)用上面的方式設(shè)置消息級(jí)別
severity = 'info' #作為例子直接將消息的級(jí)別設(shè)置為info
# severity = 'warning'
message = 'Hello World'

#使用exchang的direct模式時(shí),routing_key的值為消息的級(jí)別
channel.basic_publish(exchange='direct_logs',
      routing_key=severity,
      body=message)
print(" [x] Sent %r:%r" % (severity, message))
connection.close()
#!/usr/bin/env python
import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='direct_logs',
       exchange_type='direct')
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue
# 命令行啟動(dòng)時(shí)以參數(shù)的形式傳入要接收哪個(gè)級(jí)別的消息,可以傳入多個(gè)級(jí)別
# severities = sys.argv[1:]
# 演示使用,實(shí)際運(yùn)用應(yīng)該用上面的方式指明消息級(jí)別
# 作為演示,直接設(shè)置兩個(gè)接收級(jí)別,info 和 warning
severities = ['info', 'warning']
if not severities:
 """如果要接收消息的級(jí)別不存在則提示用戶輸入級(jí)別并退出程序"""
 sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0])
 sys.exit(1)
for severity in severities:
 """依次為每個(gè)消息級(jí)別綁定queue"""
 channel.queue_bind(exchange='direct_logs',
      queue=queue_name,
      routing_key=severity)
print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
 print(" [x] %r:%r" % (method.routing_key, body))
channel.basic_consume(callback,
      queue=queue_name,
      no_ack=True)
channel.start_consuming()

注1:exchange_type=direct時(shí),rabbitmq按消息級(jí)別發(fā)送和接收消息,接收端只能接收被指明級(jí)別的消息,其他消息,即時(shí)是由同一個(gè)發(fā)送端發(fā)送的也無法接收。當(dāng)在接收端傳入多個(gè)消息級(jí)別時(shí),應(yīng)逐個(gè)綁定消息隊(duì)列。

注2:exchange_type=direct時(shí),同樣是廣播模式,也就是如果給多個(gè)接收端指定相同的消息級(jí)別,它們都可以同時(shí)收到這一級(jí)別的消息。

例三(exchange的類型為topic):

當(dāng)exchange的類型為topic時(shí),在發(fā)送消息時(shí),應(yīng)指明消息消息的類型(比如mysql.log、qq.info等),我們可以在接收端指定接收消息類型的關(guān)鍵字(即按關(guān)鍵字接收,在類型為topic時(shí),這個(gè)關(guān)鍵字可以是一個(gè)表達(dá)式)。

import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='topic_logs',
       exchange_type='topic')
# 以命令行的方式啟動(dòng)發(fā)送端,以參數(shù)的形式傳入發(fā)送消息類型的關(guān)鍵字
routing_key = sys.argv[1] if len(sys.argv[1]) > 2 else 'anonymous.info' 
# routing_key = 'anonymous.info'
# routing_key = 'abc.orange.abc'
# routing_key = 'abc.abc.rabbit'
# routing_key = 'lazy.info'
message = ' '.join(sys.argv[2:]) or 'Hello World!'
channel.basic_publish(exchange='topic_logs',
      routing_key=routing_key,
      body=message)
print(" [x] Sent %r:%r" % (routing_key, message))
connection.close()
#!/usr/bin/env python
import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='topic_logs',
       exchange_type='topic')
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue
binding_keys = sys.argv[1:]
# binding_keys = '#'  #接收所有的消息
# binding_keys = ['*.info']  #接收所有以".info"結(jié)尾的消息
# binding_keys = ['*.orange.*'] #接收所有含有".orange."的消息
# binding_keys = ['*.*.rabbit', 'lazy.*'] #接收所有含有兩個(gè)擴(kuò)展名且結(jié)尾是".rabbit"和所有以"lazy."開頭的消息
if not binding_keys:
 sys.stderr.write("Usage: %s [binding_key]...\n" % sys.argv[0])
 sys.exit(1)
for binding_key in binding_keys:
 channel.queue_bind(exchange='topic_logs',
      queue=queue_name,
      routing_key=binding_key)
print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
 print(" [x] %r:%r" % (method.routing_key, body))
channel.basic_consume(callback,
      queue=queue_name,
      no_ack=True)
channel.start_consuming()

注:當(dāng)exchange的類型為topic時(shí),發(fā)送端與接收端的代碼都跟類型為direct時(shí)很像(基本只是變一個(gè)類型,如果接收消息類型的指定不用表達(dá)式,它們幾乎一樣),但是topic的應(yīng)用場景更廣。

注:rabbitmq指定消息的類型的表達(dá)式其實(shí)很簡單:

'#':代表接收所有的消息(一般單獨(dú)使用),使用它相當(dāng)于exchang的類型為fanout。

'*':代表任意一個(gè)字符(一般與其他單詞配合使用)。

不使用'#'或'*',使用它相當(dāng)于exchang的類型為direct。

前面介紹的都是一端發(fā)送,一端接收的消息傳遞模式,那么rabbitmq該如何實(shí)現(xiàn)客戶端和服務(wù)端都要發(fā)送和接收(即RPC)呢?

我們先來簡單了解以下RPC,RPC(Remote Procedure Call)采用客戶機(jī)/服務(wù)器模式。請(qǐng)求程序就是一個(gè)客戶機(jī),而服務(wù)提供程序就是一個(gè)服務(wù)器。首先,客戶機(jī)調(diào)用進(jìn)程發(fā)送一個(gè)有進(jìn)程參數(shù)的調(diào)用信息到服務(wù)進(jìn)程,然后等待應(yīng)答信息。在服務(wù)器端,進(jìn)程保持睡眠狀態(tài)直到調(diào)用信息到達(dá)為止。當(dāng)一個(gè)調(diào)用信息到達(dá),服務(wù)器獲得進(jìn)程參數(shù),計(jì)算結(jié)果,發(fā)送答復(fù)信息,然后等待下一個(gè)調(diào)用信息,最后,客戶端調(diào)用進(jìn)程接收答復(fù)信息,獲得進(jìn)程結(jié)果,然后調(diào)用執(zhí)行繼續(xù)進(jìn)行。

例五(通過rabbitmq實(shí)現(xiàn)rpc):

先來看以下在rabbitmq中rpc的消息傳遞模式:

我們以客戶端發(fā)送一個(gè)數(shù)字n,服務(wù)端計(jì)算出斐波那契數(shù)列的第n個(gè)數(shù)的值返回給客戶端為例。

import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='rpc_queue')
def fib(n):
 """
 計(jì)算斐波那契數(shù)列中第n個(gè)數(shù)的值
 :param n:
 :return:
 """
 if n == 0:
  return 0
 elif n == 1:
  return 1
 else:
  return fib(n-1) + fib(n-2)
def on_request(ch, method, props, body):
 n = int(body)
 print(" [.] fib(%s)" % n)
 response = fib(n)
 ch.basic_publish(exchange='',
      routing_key=props.reply_to, # 使用客戶端傳來的隊(duì)列向客戶端發(fā)送消息的處理結(jié)果
      properties=pika.BasicProperties(
       correlation_id = props.correlation_id), # 指明處理消息的id 用于客戶端確認(rèn)
      body=str(response))
 ch.basic_ack(delivery_tag = method.delivery_tag) # 未申明no_ack = True, 消息處理完畢需向rabbitmq確認(rèn)
channel.basic_qos(prefetch_count=1) # 每次只處理一條消息
channel.basic_consume(on_request, queue='rpc_queue')
print(" [x] Awaiting RPC requests")
channel.start_consuming() # 開始接收消息,未收到消息處于阻塞狀態(tài)

注1:測試時(shí),先運(yùn)行rpc_server.py,再運(yùn)行rpc_client.py。

注2:客戶端之所以每隔一秒檢測一次服務(wù)端有沒有返回結(jié)果,是因?yàn)榭蛻舳私邮諘r(shí)時(shí)無阻塞的,在這一端時(shí)間內(nèi)(不一定是1秒,但執(zhí)行的任務(wù)消耗的時(shí)間不要太長)客戶端可以執(zhí)行其他任務(wù)提高效率。

注3:為什么客戶端和服務(wù)端不使用一個(gè)隊(duì)列來傳遞消息? 答:如果使用一個(gè)隊(duì)列,以客戶端為例,它一邊在檢測這個(gè)隊(duì)列中有沒有它要接收的消息,一邊又往這個(gè)隊(duì)列里發(fā)送消息,會(huì)形成死循環(huán)。

(PS:本文例中出現(xiàn)的所有代碼是做了一些簡單修改(方便讀者理解)后的rabbitmq官方文檔中的代碼。)

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 利用Python+Java調(diào)用Shell腳本時(shí)的死鎖陷阱詳解

    利用Python+Java調(diào)用Shell腳本時(shí)的死鎖陷阱詳解

    這篇文章主要給大家介紹了關(guān)于利用Python+Java調(diào)用Shell腳本時(shí)的死鎖陷阱的相關(guān)資料,文章通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • Python3 XML 獲取雅虎天氣的實(shí)現(xiàn)方法

    Python3 XML 獲取雅虎天氣的實(shí)現(xiàn)方法

    下面小編就為大家分享一篇Python3 XML 獲取雅虎天氣的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • matplotlib.pyplot畫圖 圖片的二進(jìn)制流的獲取方法

    matplotlib.pyplot畫圖 圖片的二進(jìn)制流的獲取方法

    今天小編就為大家分享一篇matplotlib.pyplot畫圖 圖片的二進(jìn)制流的獲取方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • pandas報(bào)錯(cuò)AttributeError: DataFrame object has no attribute ix問題

    pandas報(bào)錯(cuò)AttributeError: DataFrame object has&

    這篇文章主要介紹了pandas報(bào)錯(cuò)AttributeError: DataFrame object has no attribute ix問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • Python標(biāo)準(zhǔn)庫defaultdict模塊使用示例

    Python標(biāo)準(zhǔn)庫defaultdict模塊使用示例

    這篇文章主要介紹了Python標(biāo)準(zhǔn)庫defaultdict模塊使用示例,本文講解了如何使用defaultdict給字典value元素添加默認(rèn)類型以及defaultdict的兩個(gè)使用小案例,需要的朋友可以參考下
    2015-04-04
  • Scala中使用Jsoup庫處理HTML文檔的案例分析

    Scala中使用Jsoup庫處理HTML文檔的案例分析

    Scala是一種多范式的編程語言,具有函數(shù)式編程和面向?qū)ο缶幊痰奶攸c(diǎn),同時(shí)也能夠與Java語言完美兼容,它擁有強(qiáng)大的類型推斷、高階函數(shù)、模式匹配等特性,使得代碼更加簡潔、靈活和易于維護(hù),這篇文章主要介紹了Scala中使用Jsoup庫處理HTML文檔的案例分析,需要的朋友可以參考下
    2024-04-04
  • python實(shí)現(xiàn)將json多行數(shù)據(jù)傳入到mysql中使用

    python實(shí)現(xiàn)將json多行數(shù)據(jù)傳入到mysql中使用

    這篇文章主要介紹了python實(shí)現(xiàn)將json多行數(shù)據(jù)傳入到mysql中使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Python實(shí)現(xiàn)二叉搜索樹

    Python實(shí)現(xiàn)二叉搜索樹

    二叉搜索樹(二叉排序樹)它的每個(gè)節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)為1個(gè)父節(jié)點(diǎn)指針,1個(gè)左孩子指針,1個(gè)有孩子指針,還有就是自己的數(shù)據(jù)部分了,因?yàn)橹挥凶笥覂珊⒆?所以才叫二叉樹,在此基礎(chǔ)上,該二叉樹還滿足另外一個(gè)條件:每個(gè)結(jié)點(diǎn)的左孩子都不大于該結(jié)點(diǎn)&&每個(gè)結(jié)點(diǎn)的右孩子都大于該結(jié)點(diǎn).
    2016-02-02
  • 用Python自動(dòng)清理系統(tǒng)垃圾的實(shí)現(xiàn)

    用Python自動(dòng)清理系統(tǒng)垃圾的實(shí)現(xiàn)

    這篇文章主要介紹了用Python自動(dòng)清理系統(tǒng)垃圾的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • python實(shí)現(xiàn)12306登錄并保存cookie的方法示例

    python實(shí)現(xiàn)12306登錄并保存cookie的方法示例

    這篇文章主要介紹了 python實(shí)現(xiàn)12306登錄并保存cookie的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12

最新評(píng)論