1. python簡單的並發問題
#!/usr/bin/envpython#-*-coding:utf-8-*-#author:ChanghuaGongimporttime,threading#fromurllib.requestimportRequest,urlopenpy3#fromurllib.#URLreq=urllib2.Request('http://47.93.169.69:10080/pigeon-web/user/user
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: Changhua Gong
import time,threading
# from urllib.request import Request, urlopen py3
# from urllib.error import URLError py3
import urllib2
#URL
req = urllib2.Request('http://47.93.169.69:10080/pigeon-web/user/userExtraInfo?userId=1')
#
rule = {0:500,1:30}
'''
Rule規則:0:50,第一次運行不睡眠即為0,直接並發50次;1:20,第二秒,相當於睡眠1秒,然後並發20次,
如第三秒需並發500次,則rule = {0:50,1:20,1:500}
'''
#Open url
def geturl():
time_b = time.time()
try:
response = urllib2.urlopen(req)
print(response.read().decode("utf-8")) # 列印輸出內容
except urllib2.URLError as e:
if hasattr(e, 'reason'):
print('We failed to reach a server.')
print('Reason: ', e.reason)
elif hasattr(e, 'code'):
print('The server couldn/'t fulfill the request.')
print('Error code: ', e.code)
time_e = time.time()
print("Thread %s runned for %ss" % (threading.current_thread().name, (time_e - time_b))) #線程訪問時效
if __name__=='__main__':
for k in rule:
time.sleep(k)
for i in range(rule[k]):
t = threading.Thread(target=geturl)
t.start()
2. python並發和java並發的區別
使用tornado的前提是你的服務是IO密集型的,並且你得寫非同步api,也可以請參考我簽名中的框架,把tornado改造成eventloop+threadpool (GitHub - nikoloss/iceworld: tonado的multi-thread 多線程封裝)。我們公司的android ios wap後台全是這套框架在提供服務。目前已經切換到一個分布式http響應群組裡面了,此時tornado只是作為一個中繼的gateway存在:GitHub - nikoloss/cellnest: 分布式service
在沒有阻塞的情況下,python的性能肯定不如編譯型語言。這種全非同步的模型的優勢也無法體現出來,一旦有IO操作了,這種全非同步模型的第一步accpet新連接的操作並不會暫停,也就是只要有內容抵達,至少ioloop這個環節是可以照單全收的,接收之後協程處理,隨著並發量增長它的性能下降是平穩且平滑的。反觀線程模型,如果消費數據趕不上新連接新數據的生產,性能就會直線下降。
你的700qps差不多,你可以換3.1或者3.2的tornado試試,1100~1400應該可以跑出來。當然追求一個靜態文本的輸出性能是否有必要,我覺得實際情況比這種單純的壓測要復雜的多。
3. 如何使用Python實現並發編程
多線程幾乎是每一個程序猿在使用每一種語言時都會首先想到用於解決並發的工具(JS程序員請迴避),使用多線程可以有效的利用CPU資源(Python例外)。然而多線程所帶來的程序的復雜度也不可避免,尤其是對競爭資源的同步問題。
然而在python中由於使用了全局解釋鎖(GIL)的原因,代碼並不能同時在多核上並發的運行,也就是說,Python的多線程不能並發,很多人會發現使用多線程來改進自己的Python代碼後,程序的運行效率卻下降了,這是多麼蛋疼的一件事呀!如果想了解更多細節,推薦閱讀這篇文章。實際上使用多線程的編程模型是很困難的,程序員很容易犯錯,這並不是程序員的錯誤,因為並行思維是反人類的,我們大多數人的思維是串列(精神分裂不討論),而且馮諾依曼設計的計算機架構也是以順序執行為基礎的。所以如果你總是不能把你的多線程程序搞定,恭喜你,你是個思維正常的程序猿:)
Python提供兩組線程的介面,一組是thread模塊,提供基礎的,低等級(Low Level)介面,使用Function作為線程的運行體。還有一組是threading模塊,提供更容易使用的基於對象的介面(類似於Java),可以繼承Thread對象來實現線程,還提供了其它一些線程相關的對象,例如Timer,Lock
使用thread模塊的例子
import thread
def worker():
"""thread worker function"""
print 'Worker'
thread.start_new_thread(worker)
使用threading模塊的例子
import threading
def worker():
"""thread worker function"""
print 'Worker'
t = threading.Thread(target=worker)
t.start()
或者Java Style
import threading
class worker(threading.Thread):
def __init__(self):
pass
def run():
"""thread worker function"""
print 'Worker'
t = worker()
t.start()
4. 如何優雅的編寫Python並發程序
在Python中,由於歷史原因(GIL),使得Python中多線程的效果非常不理想.GIL使得任何時刻Python只能利用一個CPU核,並
且它的調度演算法簡單粗暴:多線程中,讓每個線程運行一段時間t,然後強行掛起該線程,繼而去運行其他線程,如此周而復始,直到所有線程結束.
這使得無法有效利用計算機系統中的"局部性",頻繁的線程切換也對緩存不是很友好,造成資源的浪費.
據說Python官方曾經實現了一個去除GIL的Python解釋器,但是其效果還不如有GIL的解釋器,遂放棄.後來Python官方推出了"利
用多進程替代多線程"的方案,在Python3中也有concurrent.futures這樣的包,讓我們的程序編寫可以做到"簡單和性能兼得".
多進程/多線程+Queue
一般來說,在Python中編寫並發程序的經驗是:計算密集型任務使用多進程,IO密集型任務使用多進程或者多線程.另外,因為涉及到資源共享,所
以需要同步鎖等一系列麻煩的步驟,代碼編寫不直觀.另外一種好的思路是利用多進程/多線程+Queue的方法,可以避免加鎖這樣麻煩低效的方式.
現在在Python2中利用Queue+多進程的方法來處理一個IO密集型任務.
假設現在需要下載多個網頁內容並進行解析,單進程的方式效率很低,所以使用多進程/多線程勢在必行.
5. python gevent 能解決並發狀態嗎
1. gevent.server.StreamServer 會針對每個客戶端連接啟動一個greenlet處理,要注意的是,如果不循環監聽( 阻塞在read ),
每個greenlet會在完成後立即退出,從而導致客戶端退出( 發送FIN_ACK給客戶端 )。這個問題折騰了一晚上,終於弄明白了。坑爹啊。。。
2. 要非常仔細的檢查,greenlet處理的代碼,發現有可能阻塞IO的地方,盡量用gevent提供的庫。
3. 一些第三方庫隱藏了自己的實現( 通常是直接封裝C庫),要使得gevent兼容它們,可以用monkey_patch,但不保證全部管用。
4. 最後最後的一點,gevent的greenlet性能非常高,所以如果是用它作為並發的client端,那麼一定要注意,你的server端處理速度一定要足夠快!
否則你的客戶端代碼會因為服務端的慢速,而失去了greenlet的優勢。
6. Python 多線程並發控制問題
我想問問看你說的」訪問一個站點「是什麼意思,是下載一個文件嗎?還是需要submit一些表單上去還是其他什麼訪問法?還有多線程是用來干什麼的?是多個線程同時下載一個文件讓這個文件可以下載得更快嗎?還是其他什麼目的?
本身python訪問web就很簡單,urllib的幾個函數一調用就好了,不過不清楚你想要做什麼,所以我感覺不知道怎麼回答你。
7. Python有哪些並發方案
協程。
python的爬蟲scrapy就是採用了協程。
具體看《流程的python》第十六章。
8. 並發和並行的區別 python
並發:就是同時做多件事情。
例如:終端用戶程序利用並發功能,在輸入數據的同時響應用戶輸入。伺服器利用並發,在處理第一個請求的同時響應第二個請求。只要你希望程序同時做多件事情,就需要並發。
很多人看到「並發」就會想到「多線程」,其實他們是有區別的。多線程只是並發的一種形式,但不是唯一形式
並行:就是把正在執行的大量任務分割成小塊,分配給多個同時運行的線程。
一般情況下,為了讓CPU充分利用,並行處理都會採用多線程。
所以說:並行處理是多線程的一種,而多線程是並發的一種。
還有一種非常重要但很多人不熟悉的並發類型:非同步編程,它也是並發的一種形式。
9. 如何在Python中編寫並發程序
GIL
在Python中,由於歷史原因(GIL),使得Python中多線程的效果非常不理想.GIL使得任何時刻Python只能利用一個CPU核,並
且它的調度演算法簡單粗暴:多線程中,讓每個線程運行一段時間t,然後強行掛起該線程,繼而去運行其他線程,如此周而復始,直到所有線程結束.
這使得無法有效利用計算機系統中的"局部性",頻繁的線程切換也對緩存不是很友好,造成資源的浪費.
據說Python官方曾經實現了一個去除GIL的Python解釋器,但是其效果還不如有GIL的解釋器,遂放棄.後來Python官方推出了"利
用多進程替代多線程"的方案,在Python3中也有concurrent.futures這樣的包,讓我們的程序編寫可以做到"簡單和性能兼得".
多進程/多線程+Queue
一般來說,在Python中編寫並發程序的經驗是:計算密集型任務使用多進程,IO密集型任務使用多進程或者多線程.另外,因為涉及到資源共享,所
以需要同步鎖等一系列麻煩的步驟,代碼編寫不直觀.另外一種好的思路是利用多進程/多線程+Queue的方法,可以避免加鎖這樣麻煩低效的方式.
現在在Python2中利用Queue+多進程的方法來處理一個IO密集型任務.
假設現在需要下載多個網頁內容並進行解析,單進程的方式效率很低,所以使用多進程/多線程勢在必行.
我們可以先初始化一個tasks隊列,裡面將要存儲的是一系列dest_url,同時開啟4個進程向tasks中取任務然後執行,處理結果存儲在一個results隊列中,最後對results中的結果進行解析.最後關閉兩個隊列.
下面是一些主要的邏輯代碼.
# -*- coding:utf-8 -*-
#IO密集型任務
#多個進程同時下載多個網頁
#利用Queue+多進程
#由於是IO密集型,所以同樣可以利用threading模塊
import multiprocessing
def main():
tasks = multiprocessing.JoinableQueue()
results = multiprocessing.Queue()
cpu_count = multiprocessing.cpu_count() #進程數目==CPU核數目
create_process(tasks, results, cpu_count) #主進程馬上創建一系列進程,但是由於阻塞隊列tasks開始為空,副進程全部被阻塞
add_tasks(tasks) #開始往tasks中添加任務
parse(tasks, results) #最後主進程等待其他線程處理完成結果
def create_process(tasks, results, cpu_count):
for _ in range(cpu_count):
p = multiprocessing.Process(target=_worker, args=(tasks, results)) #根據_worker創建對應的進程
p.daemon = True #讓所有進程可以隨主進程結束而結束
p.start() #啟動
def _worker(tasks, results):
while True: #因為前面所有線程都設置了daemon=True,故不會無限循環
try:
task = tasks.get() #如果tasks中沒有任務,則阻塞
result = _download(task)
results.put(result) #some exceptions do not handled
finally:
tasks.task_done()
def add_tasks(tasks):
for url in get_urls(): #get_urls() return a urls_list
tasks.put(url)
def parse(tasks, results):
try:
tasks.join()
except KeyboardInterrupt as err:
print "Tasks has been stopped!"
print err
while not results.empty():
_parse(results)
if __name__ == '__main__':
main()
利用Python3中的concurrent.futures包
在Python3中可以利用concurrent.futures包,編寫更加簡單易用的多線程/多進程代碼.其使用感覺和Java的concurrent框架很相似(借鑒?)
比如下面的簡單代碼示例
def handler():
futures = set()
with concurrent.futures.ProcessPoolExecutor(max_workers=cpu_count) as executor:
for task in get_task(tasks):
future = executor.submit(task)
futures.add(future)
def wait_for(futures):
try:
for future in concurrent.futures.as_completed(futures):
err = futures.exception()
if not err:
result = future.result()
else:
raise err
except KeyboardInterrupt as e:
for future in futures:
future.cancel()
print "Task has been canceled!"
print e
return result
總結
要是一些大型Python項目也這般編寫,那麼效率也太低了.在Python中有許多已有的框架使用,使用它們起來更加高效.
10. Python進程之並行與並發的區別
並行 :
當系統有一個以上CPU時,則進程的操作有可能非並發。當一個CPU執行一個進程時,另一個CPU可以執行另一個進程,兩個進程互不搶佔CPU資源,可以同時進行,這種方式我們稱之為並行。
並發 :
當有多個進程在操作時,如果系統只有一個CPU,則它根本不可能真正同時執行一個以上的進程,它只能把CPU運行時間劃分成若干個時間段,再將時間 段分配給各個進程執行,在一個時間段的進程代碼運行時,其它進程處於掛起狀,這種方式我們稱之為並發。
區別:
並發和並行是即相似又有區別的兩個概念,並行是指兩個或者多個事件在同一時刻同時執行,而並發是指兩個或多個事件通過時間片輪流被執行。在多道程序環境下,並發性是指在一段時間內宏觀上有多個程序在同時運行,但在單核CPU中,同一時刻僅能有一道程序執行,故微觀上這些程序只能是分時地交替執行。倘若在計算機中有多個CPU,則這些可以並發執行的程序便可被分配到多個處理機上,實現並行執行,即利用每個處理機來處理一個可並發執行的程序,這樣,多個程序便可以同時執行。
相關推薦:《Python視頻教程》
進程的狀態如下圖所示
在了解其他概念之前,我們首先要了解進程的幾個狀態。在程序運行的過程中,由於被操作系統的調度演算法控制,程序會進入幾個狀態:就緒,運行和阻塞。
(1)就緒(Ready)狀態
當進程已分配到除CPU以外的所有必要的資源,只要獲得處理機便可立即執行,這時的進程狀態稱為就緒狀態。
(2)執行/運行(Running)狀態當進程已獲得處理機,其程序正在處理機上執行,此時的進程狀態稱為執行狀態。
(3)阻塞(Blocked)狀態正在執行的進程,由於等待某個事件發生而無法執行時,便放棄處理機而處於阻塞狀態。引起進程阻塞的事件可有多種,例如,等待I/O完成、申請緩沖區不能滿足、等待信件(信號)等。
相關推薦:
一文帶你讀懂Python中的進程