導航:首頁 > 編程語言 > python實現消息隊列

python實現消息隊列

發布時間:2023-08-22 08:28:43

python基礎(21)-線程通信

到這里,我們要聊一下線程通信的內容;
首先,我們拋開語言不談,先看看比較基礎的東西,線程間通信的方式;其實也就是哪幾種(我這里說的,是我的所謂的知道的。。。)事件,消息隊列,信號量,條件變數(鎖算不算?我只是認為是同步的一種);所以我們也就是要把這些掌握了,因為各有各的好處嘛;
條件變數我放到了上面的線程同步裡面講了,我總感覺這算是同步的一種,沒有很多具體信息的溝通;同時吧,我認為條件變數比較重要,因為這種可以應用於線程池的操作上;所以比較重要;這里,拋開條件變數不談,我們看看其他的東西;
1、消息隊列:
queue 模塊下提供了幾個阻塞隊列,這些隊列主要用於實現線程通信。在 queue 模塊下主要提供了三個類,分別代表三種隊列,它們的主要區別就在於進隊列、出隊列的不同。

關於這三個隊列類的簡單介紹如下:
queue.Queue(maxsize=0):代表 FIFO(先進先出)的常規隊列,maxsize 可以限制隊列的大小。如果隊列的大小達到隊列的上限,就會加鎖,再次加入元素時就會被阻塞,直到隊列中的元素被消費。如果將 maxsize 設置為 0 或負數,則該隊列的大小就是無限制的。
queue.LifoQueue(maxsize=0):代表 LIFO(後進先出)的隊列,與 Queue 的區別就是出隊列的順序不同。
PriorityQueue(maxsize=0):代表優先順序隊列,優先順序最小的元素先出隊列。

這三個隊列類的屬性和方法基本相同, 它們都提供了如下屬性和方法:
Queue.qsize():返回隊列的實際大小,也就是該隊列中包含幾個元素。
Queue.empty():判斷隊列是否為空。
Queue.full():判斷隊列是否已滿。
Queue.put(item, block=True, timeout=None):向隊列中放入元素。如果隊列己滿,且 block 參數為 True(阻塞),當前線程被阻塞,timeout 指定阻塞時間,如果將 timeout 設置為 None,則代表一直阻塞,直到該隊列的元素被消費;如果隊列己滿,且 block 參數為 False(不阻塞),則直接引發 queue.FULL 異常。
Queue.put_nowait(item):向隊列中放入元素,不阻塞。相當於在上一個方法中將 block 參數設置為 False。
Queue.get(item, block=True, timeout=None):從隊列中取出元素(消費元素)。如果隊列已滿,且 block 參數為 True(阻塞),當前線程被阻塞,timeout 指定阻塞時間,如果將 timeout 設置為 None,則代表一直阻塞,直到有元素被放入隊列中; 如果隊列己空,且 block 參數為 False(不阻塞),則直接引發 queue.EMPTY 異常。
Queue.get_nowait(item):從隊列中取出元素,不阻塞。相當於在上一個方法中將 block 參數設置為 False。
其實我們想想,這個隊列,是python進行封裝的,那麼我們可以用在線程間的通信;同時也是可以用做一個數據結構;先進先出就是隊列,後進先出就是棧;我們用這個棧寫個十進制轉二進制的例子:

沒毛病,可以正常的列印;其中需要注意的就是,maxsize在初始化的時候如果是0或者是個負數的話,那麼就會是不限制大小;
那麼其實我們想想,我們如果用做線程通信的話,我們兩個線程,可以把隊列設置為1的大小,如果是1對多,比如是創建者和消費者的關系,我們完全可以作為消息隊列,比如說創建者一直在創建一些東西,然後放入到消息隊列裡面,然後供消費著使用;就是一個很好的例子;所以,其實說是消息隊列,也就是隊列,沒差;
=====================================================================
下面來看一下事件
Event 是一種非常簡單的線程通信機制,一個線程發出一個 Event,另一個線程可通過該 Event 被觸發。

Event 本身管理一個內部旗標,程序可以通過 Event 的 set() 方法將該旗標設置為 True,也可以調用 clear() 方法將該旗標設置為 False。程序可以調用 wait() 方法來阻塞當前線程,直到 Event 的內部旗標被設置為 True。

Event 提供了如下方法:
is_set():該方法返回 Event 的內部旗標是否為True。
set():該方法將會把 Event 的內部旗標設置為 True,並喚醒所有處於等待狀態的線程。
clear():該方法將 Event 的內部旗標設置為 False,通常接下來會調用 wait() 方法來阻塞當前線程。
wait(timeout=None):該方法會阻塞當前線程。
這里我想解釋一下;其實對於事件來說,事件可以看成和條件變數是一樣的,只是我們說說不一樣的地方;
1、對於事件來說,一旦觸發了事件,也就是說,一旦set為true了,那麼就會一直為true,需要clear調內部的標志,才能繼續wait;但是conditon不是,他是一次性的喚醒其他線程;
2、conditon自己帶鎖;事件呢?不是的;沒有自己的鎖;比如說有一個存錢的線程,有一個是取錢的線程;那麼存錢的線程要存錢;需要怎麼辦呢?1、發現銀行沒有錢了(is_set判斷);2、鎖住銀行;3、存錢;4、釋放銀行;5、喚醒事件;對於取錢的人;1、判斷是否有錢;2、被喚醒了,然後鎖住銀行;3、開始取錢;4、清理告訴存錢的人,我沒錢了(clear);5、釋放鎖;6、等著錢存進去;
其實說白了,就是記住一點;這個旗標需要自己clear就對了
寫個例子,怕以後忘了怎麼用;

其實時間和信號量比較像;但是信號量不用自己清除標志位;但是事件是需要的;

Ⅱ Python能做什麼,能夠開發什麼項目

Python是一種計算機程序設計語言。是一種面向對象的動態類型語言,最初被設計用於編寫自動化腳本(shell),隨著版本的不斷更新和語言新功能的添加,越來越多被用於獨立的、大型項目的開發。

Python是一種解釋型腳本語言,可以應用於Web 和 Internet開發、科學計算和統計、人工智慧、教育、桌面界面開發、軟體開發、後端開發這些領域。

Python的應用

1、系統編程

提供API(Application Programming Interface應用程序編程介面),能方便進行系統維護和管理,Linux下標志性語言之一,是很多系統管理員理想的編程工具。

2、圖形處理

有PIL、Tkinter等圖形庫支持,能方便進行圖形處理。

3、數學處理

NumPy擴展提供大量與許多標准數學庫的介面。

4、文本處理

python提供的re模塊能支持正則表達式,還提供SGML,XML分析模塊,許多程序員利用python進行XML程序的開發。


5、資料庫編程

程序員可通過遵循Python DB-API(資料庫應用程序編程介面)規范的模塊與Microsoft SQL Server,Oracle,Sybase,DB2,MySQL、SQLite等資料庫通信。python自帶有一個Gadfly模塊,提供了一個完整的SQL環境。

6、網路編程

提供豐富的模塊支持sockets編程,能方便快速地開發分布式應用程序。很多大規模軟體開發計劃例如Zope,Mnet 及BitTorrent. Google都在廣泛地使用它。

7、Web編程

應用的開發語言,支持最新的XML技術。

8、多媒體應用

Python的PyOpenGL模塊封裝了「OpenGL應用程序編程介面」,能進行二維和三維圖像處理。PyGame模塊可用於編寫游戲軟體。

9、pymo引擎

PYMO全稱為python memories off,是一款運行於Symbian S60V3,Symbian3,S60V5, Symbian3, Android系統上的AVG游戲引擎。因其基於python2.0平台開發,並且適用於創建秋之回憶(memories off)風格的AVG游戲,故命名為PYMO。

10、黑客編程

python有一個hack的庫,內置了你熟悉的或不熟悉的函數,但是缺少成就感。

Ⅲ Python與java如何構建通信請給出一個學習方向。

1、python提供restful介面,java直接調用restful api即可;
2、rpc通信,現成框架例如grpc。 java 和python都支持。
3、消息隊列,python計算結果存到消息隊列,java端訂閱處理即可。相當於引入一個中間代理角色。
思路大概就上面的方式,根據實際場景進行技術選型。

Ⅳ 如何在後台部署深度學習模型

搭建深度學習後台伺服器

我們的Keras深度學習REST API將能夠批量處理圖像,擴展到多台機器(包括多台web伺服器和Redis實例),並在負載均衡器之後進行循環調度。

為此,我們將使用:

Ⅳ python入門需要學哪些

初學者學習Python需循序漸進,可以從以下內容入手學習:

1.Python基礎知識

學習任何一門編程語言都需要學習相關語法知識,Python基礎知識的學習主要包括Python解釋器執行原理、字元編碼、注釋、變數、縮進、流程式控制制、文件操作、數據類型、數據類型內置方法、字元串格式化、運算符、輸入輸出、三元運算、collections、列表、字典、元組、集合、IO操作、文件增刪改查、函數等。

5.資料庫、緩存、隊列

Python資料庫、緩存、隊列學習內容為Python操作redis、Python操作memcache、rabbitMQ消息隊列、資料庫介紹、mysql資料庫安裝使用、mysql管理、mysql數據類型、常用mysql命令、創建資料庫、外鍵、增刪改查表、許可權、事務、索引、Python操作mysql等。

6.Web開發基礎

Python之Web開發基礎學習內容為HTML基礎、CSS基礎、JavaScript基礎、局部變數和全局變數、集合、數組、字典、函數參數、原型、面向對象、作用域、dom編程、jquery介紹、jquery選擇器、jquery屬性和CSS操作、jquery文檔處理、jquery篩選、jquery事件託管、jquery事件、jquery ajax、jquery擴展方法、bootstrap使用、EasyUI介紹和使用等。

7.Web框架學習

Python之Web框架學習內容為Web框架本質、socket伺服器、基於反射的路由系統、WSGI介凱閉行紹及原理實現態御、開發自己的Web框架、MVC和MTV、路由系統、模板、django基礎學習與使用、普通路由和動態路由、模板引擎、ORM介紹、Django ORM增刪改查學習、自定義tag、django進階學習與使用、模型綁定、Form表單驗證、Django ORM進階學習、ModelForm、自定義Validator等。

Ⅵ Python中Flask框架的變數和函數

可以從模板中直接訪問Flask當前的config對象:

就是flask中代表當前請求的request對象:

輸出結果為(本機本地運行):

為Flask的session對象
{{ session.get('name') }}
輸出結果為(本機本地運行):檔蠢

url_for會緩運根據傳入的路由器函數名,返回該路由對應的URL,在模板中始終使用url_for()就可以安全的修改路由綁定的URL,則不比擔心模板中渲染出錯的鏈接,經常用於超鏈接,比如下面的例子:

點擊即可跳轉至主頁

同時,如果定義的路由URL是帶有參數的,可以把它們作為關鍵字參數傳入url_for(),Flask會把他們填擾蠢梁充進最終生成的URL中:

這個函數會返回之前在flask中通過flask()傳入的消息的列表,flash函數可以把由Python字元串表示的消息加入一個消息隊列中,再使用get_flashed_message()函數取出它們並消費掉:

Ⅶ 一篇文章帶你深度解析Python線程和進程

使用Python中的線程模塊,能夠同時運行程序的不同部分,並簡化設計。如果你已經入門Python,並且想用線程來提升程序運行速度的話,希望這篇教程會對你有所幫助。

線程與進程

什麼是進程

進程是系統進行資源分配和調度的一個獨立單位 進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。每個進程都有自己的獨立內存空間,不同進程通過進程間通信來通信。由於進程比較重量,占據獨立的內存,所以上下文進程間的切換開銷(棧、寄存器、虛擬內存、文件句柄等)比較大,但相對比較穩定安全。

什麼是線程

CPU調度和分派的基本單位 線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。線程間通信主要通過共享內存,上下文切換很快,資源開銷較少,但相比進程不夠穩定容易丟失數據。

進程與線程的關系圖

線程與進程的區別:

進程

現實生活中,有很多的場景中的事情是同時進行的,比如開車的時候 手和腳共同來駕駛 汽車 ,比如唱歌跳舞也是同時進行的,再比如邊吃飯邊打電話;試想如果我們吃飯的時候有一個領導來電,我們肯定是立刻就接聽了。但是如果你吃完飯再接聽或者回電話,很可能會被開除。

注意:

多任務的概念

什麼叫 多任務 呢?簡單地說,就是操作系統可以同時運行多個任務。打個比方,你一邊在用瀏覽器上網,一邊在聽MP3,一邊在用Word趕作業,這就是多任務,至少同時有3個任務正在運行。還有很多任務悄悄地在後台同時運行著,只是桌面上沒有顯示而已。

現在,多核CPU已經非常普及了,但是,即使過去的單核CPU,也可以執行多任務。由於CPU執行代碼都是順序執行的,那麼,單核CPU是怎麼執行多任務的呢?

答案就是操作系統輪流讓各個任務交替執行,任務1執行0.01秒,切換到任務2,任務2執行0.01秒,再切換到任務3,執行0.01秒,這樣反復執行下去。表面上看,每個任務都是交替執行的,但是,由於CPU的執行速度實在是太快了,我們感覺就像所有任務都在同時執行一樣。

真正的並行執行多任務只能在多核CPU上實現,但是,由於任務數量遠遠多於CPU的核心數量,所以,操作系統也會自動把很多任務輪流調度到每個核心上執行。 其實就是CPU執行速度太快啦!以至於我們感受不到在輪流調度。

並行與並發

並行(Parallelism)

並行:指兩個或兩個以上事件(或線程)在同一時刻發生,是真正意義上的不同事件或線程在同一時刻,在不同CPU資源呢上(多核),同時執行。

特點

並發(Concurrency)

指一個物理CPU(也可以多個物理CPU) 在若幹道程序(或線程)之間多路復用,並發性是對有限物理資源強制行使多用戶共享以提高效率。

特點

multiprocess.Process模塊

process模塊是一個創建進程的模塊,藉助這個模塊,就可以完成進程的創建。

語法:Process([group [, target [, name [, args [, kwargs]]]]])

由該類實例化得到的對象,表示一個子進程中的任務(尚未啟動)。

注意:1. 必須使用關鍵字方式來指定參數;2. args指定的為傳給target函數的位置參數,是一個元祖形式,必須有逗號。

參數介紹:

group:參數未使用,默認值為None。

target:表示調用對象,即子進程要執行的任務。

args:表示調用的位置參數元祖。

kwargs:表示調用對象的字典。如kwargs = {'name':Jack, 'age':18}。

name:子進程名稱。

代碼:

除了上面這些開啟進程的方法之外,還有一種以繼承Process的方式開啟進程的方式:

通過上面的研究,我們千方百計實現了程序的非同步,讓多個任務可以同時在幾個進程中並發處理,他們之間的運行沒有順序,一旦開啟也不受我們控制。盡管並發編程讓我們能更加充分的利用IO資源,但是也給我們帶來了新的問題。

當多個進程使用同一份數據資源的時候,就會引發數據安全或順序混亂問題,我們可以考慮加鎖,我們以模擬搶票為例,來看看數據安全的重要性。

加鎖可以保證多個進程修改同一塊數據時,同一時間只能有一個任務可以進行修改,即串列的修改。加鎖犧牲了速度,但是卻保證了數據的安全。

因此我們最好找尋一種解決方案能夠兼顧:1、效率高(多個進程共享一塊內存的數據)2、幫我們處理好鎖問題。

mutiprocessing模塊為我們提供的基於消息的IPC通信機制:隊列和管道。隊列和管道都是將數據存放於內存中 隊列又是基於(管道+鎖)實現的,可以讓我們從復雜的鎖問題中解脫出來, 我們應該盡量避免使用共享數據,盡可能使用消息傳遞和隊列,避免處理復雜的同步和鎖問題,而且在進程數目增多時,往往可以獲得更好的可獲展性( 後續擴展該內容 )。

線程

Python的threading模塊

Python 供了幾個用於多線程編程的模塊,包括 thread, threading 和 Queue 等。thread 和 threading 模塊允許程序員創建和管理線程。thread 模塊 供了基本的線程和鎖的支持,而 threading 供了更高級別,功能更強的線程管理的功能。Queue 模塊允許用戶創建一個可以用於多個線程之間 共享數據的隊列數據結構。

python創建和執行線程

創建線程代碼

1. 創建方法一:

2. 創建方法二:

進程和線程都是實現多任務的一種方式,例如:在同一台計算機上能同時運行多個QQ(進程),一個QQ可以打開多個聊天窗口(線程)。資源共享:進程不能共享資源,而線程共享所在進程的地址空間和其他資源,同時,線程有自己的棧和棧指針。所以在一個進程內的所有線程共享全局變數,但多線程對全局變數的更改會導致變數值得混亂。

代碼演示:

得到的結果是:

首先需要明確的一點是GIL並不是Python的特性,它是在實現Python解析器(CPython)時所引入的一個概念。就好比C++是一套語言(語法)標准,但是可以用不同的編譯器來編譯成可執行代碼。同樣一段代碼可以通過CPython,PyPy,Psyco等不同的Python執行環境來執行(其中的JPython就沒有GIL)。

那麼CPython實現中的GIL又是什麼呢?GIL全稱Global Interpreter Lock為了避免誤導,我們還是來看一下官方給出的解釋:

主要意思為:

因此,解釋器實際上被一個全局解釋器鎖保護著,它確保任何時候都只有一個Python線程執行。在多線程環境中,Python 虛擬機按以下方式執行:

由於GIL的存在,Python的多線程不能稱之為嚴格的多線程。因為 多線程下每個線程在執行的過程中都需要先獲取GIL,保證同一時刻只有一個線程在運行。

由於GIL的存在,即使是多線程,事實上同一時刻只能保證一個線程在運行, 既然這樣多線程的運行效率不就和單線程一樣了嗎,那為什麼還要使用多線程呢?

由於以前的電腦基本都是單核CPU,多線程和單線程幾乎看不出差別,可是由於計算機的迅速發展,現在的電腦幾乎都是多核CPU了,最少也是兩個核心數的,這時差別就出來了:通過之前的案例我們已經知道,即使在多核CPU中,多線程同一時刻也只有一個線程在運行,這樣不僅不能利用多核CPU的優勢,反而由於每個線程在多個CPU上是交替執行的,導致在不同CPU上切換時造成資源的浪費,反而會更慢。即原因是一個進程只存在一把gil鎖,當在執行多個線程時,內部會爭搶gil鎖,這會造成當某一個線程沒有搶到鎖的時候會讓cpu等待,進而不能合理利用多核cpu資源。

但是在使用多線程抓取網頁內容時,遇到IO阻塞時,正在執行的線程會暫時釋放GIL鎖,這時其它線程會利用這個空隙時間,執行自己的代碼,因此多線程抓取比單線程抓取性能要好,所以我們還是要使用多線程的。

GIL對多線程Python程序的影響

程序的性能受到計算密集型(CPU)的程序限制和I/O密集型的程序限制影響,那什麼是計算密集型和I/O密集型程序呢?

計算密集型:要進行大量的數值計算,例如進行上億的數字計算、計算圓周率、對視頻進行高清解碼等等。這種計算密集型任務雖然也可以用多任務完成,但是花費的主要時間在任務切換的時間,此時CPU執行任務的效率比較低。

IO密集型:涉及到網路請求(time.sleep())、磁碟IO的任務都是IO密集型任務,這類任務的特點是CPU消耗很少,任務的大部分時間都在等待IO操作完成(因為IO的速度遠遠低於CPU和內存的速度)。對於IO密集型任務,任務越多,CPU效率越高,但也有一個限度。

當然為了避免GIL對我們程序產生影響,我們也可以使用,線程鎖。

Lock&RLock

常用的資源共享鎖機制:有Lock、RLock、Semphore、Condition等,簡單給大家分享下Lock和RLock。

Lock

特點就是執行速度慢,但是保證了數據的安全性

RLock

使用鎖代碼操作不當就會產生死鎖的情況。

什麼是死鎖

死鎖:當線程A持有獨占鎖a,並嘗試去獲取獨占鎖b的同時,線程B持有獨占鎖b,並嘗試獲取獨占鎖a的情況下,就會發生AB兩個線程由於互相持有對方需要的鎖,而發生的阻塞現象,我們稱為死鎖。即死鎖是指多個進程因競爭資源而造成的一種僵局,若無外力作用,這些進程都將無法向前推進。

所以,在系統設計、進程調度等方面注意如何不讓這四個必要條件成立,如何確定資源的合理分配演算法,避免進程永久占據系統資源。

死鎖代碼

python線程間通信

如果各個線程之間各干各的,確實不需要通信,這樣的代碼也十分的簡單。但這一般是不可能的,至少線程要和主線程進行通信,不然計算結果等內容無法取回。而實際情況中要復雜的多,多個線程間需要交換數據,才能得到正確的執行結果。

python中Queue是消息隊列,提供線程間通信機制,python3中重名為為queue,queue模塊塊下提供了幾個阻塞隊列,這些隊列主要用於實現線程通信。

在 queue 模塊下主要提供了三個類,分別代表三種隊列,它們的主要區別就在於進隊列、出隊列的不同。

簡單代碼演示

此時代碼會阻塞,因為queue中內容已滿,此時可以在第四個queue.put('蘋果')後面添加timeout,則成為 queue.put('蘋果',timeout=1)如果等待1秒鍾仍然是滿的就會拋出異常,可以捕獲異常。

同理如果隊列是空的,無法獲取到內容默認也會阻塞,如果不阻塞可以使用queue.get_nowait()。

在掌握了 Queue 阻塞隊列的特性之後,在下面程序中就可以利用 Queue 來實現線程通信了。

下面演示一個生產者和一個消費者,當然都可以多個

使用queue模塊,可在線程間進行通信,並保證了線程安全。

協程

協程,又稱微線程,纖程。英文名Coroutine。

協程是python個中另外一種實現多任務的方式,只不過比線程更小佔用更小執行單元(理解為需要的資源)。為啥說它是一個執行單元,因為它自帶CPU上下文。這樣只要在合適的時機, 我們可以把一個協程 切換到另一個協程。只要這個過程中保存或恢復 CPU上下文那麼程序還是可以運行的。

通俗的理解:在一個線程中的某個函數,可以在任何地方保存當前函數的一些臨時變數等信息,然後切換到另外一個函數中執行,注意不是通過調用函數的方式做到的,並且切換的次數以及什麼時候再切換到原來的函數都由開發者自己確定。

在實現多任務時,線程切換從系統層面遠不止保存和恢復 CPU上下文這么簡單。操作系統為了程序運行的高效性每個線程都有自己緩存Cache等等數據,操作系統還會幫你做這些數據的恢復操作。所以線程的切換非常耗性能。但是協程的切換只是單純的操作CPU的上下文,所以一秒鍾切換個上百萬次系統都抗的住。

greenlet與gevent

為了更好使用協程來完成多任務,除了使用原生的yield完成模擬協程的工作,其實python還有的greenlet模塊和gevent模塊,使實現協程變的更加簡單高效。

greenlet雖說實現了協程,但需要我們手工切換,太麻煩了,gevent是比greenlet更強大的並且能夠自動切換任務的模塊。

其原理是當一個greenlet遇到IO(指的是input output 輸入輸出,比如網路、文件操作等)操作時,比如訪問網路,就自動切換到其他的greenlet,等到IO操作完成,再在適當的時候切換回來繼續執行。

模擬耗時操作:

如果有耗時操作也可以換成,gevent中自己實現的模塊,這時候就需要打補丁了。

使用協程完成一個簡單的二手房信息的爬蟲代碼吧!

以下文章來源於Python專欄 ,作者宋宋

文章鏈接:https://mp.weixin.qq.com/s/2r3_ipU3HjdA5VnqSHjUnQ

閱讀全文

與python實現消息隊列相關的資料

熱點內容
怎樣不用海綿做解壓玩具 瀏覽:77
為什麼遠程伺服器復制不了文件 瀏覽:711
打開app閃退怎麼回事 瀏覽:748
bcrpt加密原理 瀏覽:399
女程序員寫的小說 瀏覽:774
華為路由器ip設置命令 瀏覽:552
如何打開軟體伺服器 瀏覽:756
單片機介面技術及應用 瀏覽:751
linux下執行腳本文件 瀏覽:127
撥號加密保護 瀏覽:435
b站彈幕加密 瀏覽:601
交友盲盒源碼破解 瀏覽:248
單片機100位百位符號 瀏覽:686
用友通加密狗壞了 瀏覽:550
如何在伺服器上配置外網網址 瀏覽:844
阿里雲伺服器的硬體在哪裡 瀏覽:54
python自動注冊谷歌 瀏覽:330
phpini驗證碼 瀏覽:826
解壓後的文件怎麼驅動 瀏覽:328
老闆要程序員加班 瀏覽:416