⑴ python實現多線程並發執行
由於停服維護的需求(服務越來越多的原因),此前編寫的shell腳本執行速度緩慢(for循環,這就會很慢),為提高執行速度,參考很多資料,完成此腳本,實現並發執行機制.(當然這是測試腳本,有需要的同學,拿去改ba改ba,應該就可以用了)
此處腳本參考了 https://www.jb51.net/article/86053.htm
⑵ python 怎麼實現多線程的
線程也就是輕量級的進程,多線程允許一次執行多個線程,Python是多線程語言,它有一個多線程包,GIL也就是全局解釋器鎖,以確保一次執行單個線程,一個線程保存GIL並在將其傳遞給下一個線程之前執行一些操作,也就產生了並行執行的錯覺。
⑶ Python的keyboard模塊使用多線程
在Python的keyboard模塊中,使用了線程來處理鍵盤事件。具體來說,keyboard模塊使用了Python標准庫中的threading模塊來創建線程,以便在後台監視鍵盤事件並在發生事件時調用回調函數。
當你使用keyboard模塊的add_hotkey()函數注冊熱鍵時,模塊會創建一個新的線程來監緩襪視鍵盤事件。當你按下熱鍵時,這個線程會在後台調用你提供的回調函數。
在使擾含激用keyboard模塊時,你不需要顯式地創建或控制線程,模塊會在內部處理線程的創建和管理。如果你需要在程序中使用多線程來老孫完成其他任務,可以通過Python標准庫中的threading模塊來創建新的線程。
需要注意的是,在使用多線程時,需要注意線程之間的同步和互斥,以避免競爭條件和死鎖等問題。建議在使用多線程時仔細閱讀Python官方文檔,並使用線程安全的工具和技術來編寫多線程程序。
⑷ python多線程有什麼作用
線程在程序中是獨立的、並發的執行流。與分隔的進程相比,進程中線程之間的隔離程度要小,它們共享內存、文件句柄和其他進程應有的狀態。
因為線程的劃分尺度小於進程,使得多線程程序的並發性高。進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。
線程比進程具有更高的性能,這是由於同一個進程中的線程都有共性多個線程共享同一個進程的虛擬空間。線程共享的環境包括進程代碼段、進程的公有數據等,利用這些共享的數據,線程之間很容易實現通信。
操作系統在創建進程時,必須為該進程分配獨立的內存空間,並分配大量的相關資源,但創建線程則簡單得多。因此,使用多線程來實現並發比使用多進程的性能要高得多。
總結起來,使用多線程編程具有如下幾個優點:
進程之間不能共享內存,但線程之間共享內存非常容易。
操作系統在創建進程時,需要為該進程重新分配系統資源,但創建線程的代價則小得多。因此,使用多線程來實現多任務並發執行比使用多進程的效率高。
Python語言內置了多線程功能支持,而不是單純地作為底層操作系統的調度方式,從而簡化了 Python 的多線程編程。
在實際應用中,多線程是非常有用的。比如一個瀏覽器必須能同時下載多張圖片;一個 Web 伺服器必須能同時響應多個用戶請求;圖形用戶界面(GUI)應用也需要啟動單獨的線程,從主機環境中收集用戶界面事件……總之,多線程在實際編程中的應用是非常廣泛的。
⑸ Python多線程總結
在實際處理數據時,因系統內存有限,我們不可能一次把所有數據都導出進行操作,所以需要批量導出依次操作。為了加快運行,我們會採用多線程的方法進行數據處理, 以下為我總結的多線程批量處理數據的模板:
主要分為三大部分:
共分4部分對多線程的內容進行總結。
先為大家介紹線程的相關概念:
在飛車程序中,如果沒有多線程,我們就不能一邊聽歌一邊玩飛車,聽歌與玩 游戲 不能並行;在使用多線程後,我們就可以在玩 游戲 的同時聽背景音樂。在這個例子中啟動飛車程序就是一個進程,玩 游戲 和聽音樂是兩個線程。
Python 提供了 threading 模塊來實現多線程:
因為新建線程系統需要分配資源、終止線程系統需要回收資源,所以如果可以重用線程,則可以減去新建/終止的開銷以提升性能。同時,使用線程池的語法比自己新建線程執行線程更加簡潔。
Python 為我們提供了 ThreadPoolExecutor 來實現線程池,此線程池默認子線程守護。它的適應場景為突發性大量請求或需要大量線程完成任務,但實際任務處理時間較短。
其中 max_workers 為線程池中的線程個數,常用的遍歷方法有 map 和 submit+as_completed 。根據業務場景的不同,若我們需要輸出結果按遍歷順序返回,我們就用 map 方法,若想誰先完成就返回誰,我們就用 submit+as_complete 方法。
我們把一個時間段內只允許一個線程使用的資源稱為臨界資源,對臨界資源的訪問,必須互斥的進行。互斥,也稱間接制約關系。線程互斥指當一個線程訪問某臨界資源時,另一個想要訪問該臨界資源的線程必須等待。當前訪問臨界資源的線程訪問結束,釋放該資源之後,另一個線程才能去訪問臨界資源。鎖的功能就是實現線程互斥。
我把線程互斥比作廁所包間上大號的過程,因為包間里只有一個坑,所以只允許一個人進行大號。當第一個人要上廁所時,會將門上上鎖,這時如果第二個人也想大號,那就必須等第一個人上完,將鎖解開後才能進行,在這期間第二個人就只能在門外等著。這個過程與代碼中使用鎖的原理如出一轍,這里的坑就是臨界資源。 Python 的 threading 模塊引入了鎖。 threading 模塊提供了 Lock 類,它有如下方法加鎖和釋放鎖:
我們會發現這個程序只會列印「第一道鎖」,而且程序既沒有終止,也沒有繼續運行。這是因為 Lock 鎖在同一線程內第一次加鎖之後還沒有釋放時,就進行了第二次 acquire 請求,導致無法執行 release ,所以鎖永遠無法釋放,這就是死鎖。如果我們使用 RLock 就能正常運行,不會發生死鎖的狀態。
在主線程中定義 Lock 鎖,然後上鎖,再創建一個子 線程t 運行 main 函數釋放鎖,結果正常輸出,說明主線程上的鎖,可由子線程解鎖。
如果把上面的鎖改為 RLock 則報錯。在實際中設計程序時,我們會將每個功能分別封裝成一個函數,每個函數中都可能會有臨界區域,所以就需要用到 RLock 。
一句話總結就是 Lock 不能套娃, RLock 可以套娃; Lock 可以由其他線程中的鎖進行操作, RLock 只能由本線程進行操作。
⑹ python 多進程和多線程配合
由於python的多線程中存在PIL鎖,因此python的多線程不能利用多核,那麼,由於現在的計算機是多核的,就不能充分利用計算機的多核資源。但是python中的多進程是可以跑在不同的cpu上的。因此,嘗試了多進程+多線程的方式,來做一個任務。比如:從中科大的鏡像源中下載多個rpm包。
#!/usr/bin/pythonimport reimport commandsimport timeimport multiprocessingimport threadingdef download_image(url):
print '*****the %s rpm begin to download *******' % url
commands.getoutput('wget %s' % url)def get_rpm_url_list(url):
commands.getoutput('wget %s' % url)
rpm_info_str = open('index.html').read()
regu_mate = '(?<=<a href=")(.*?)(?=">)'
rpm_list = re.findall(regu_mate, rpm_info_str)
rpm_url_list = [url + rpm_name for rpm_name in rpm_list] print 'the count of rpm list is: ', len(rpm_url_list) return rpm_url_
def multi_thread(rpm_url_list):
threads = [] # url = 'https://mirrors.ustc.e.cn/centos/7/os/x86_64/Packages/'
# rpm_url_list = get_rpm_url_list(url)
for index in range(len(rpm_url_list)): print 'rpm_url is:', rpm_url_list[index]
one_thread = threading.Thread(target=download_image, args=(rpm_url_list[index],))
threads.append(one_thread)
thread_num = 5 # set threading pool, you have put 4 threads in it
while 1:
count = min(thread_num, len(threads)) print '**********count*********', count ###25,25,...6707%25
res = [] for index in range(count):
x = threads.pop()
res.append(x) for thread_index in res:
thread_index.start() for j in res:
j.join() if not threads:
def multi_process(rpm_url_list):
# process num at the same time is 4
process = []
rpm_url_group_0 = []
rpm_url_group_1 = []
rpm_url_group_2 = []
rpm_url_group_3 = [] for index in range(len(rpm_url_list)): if index % 4 == 0:
rpm_url_group_0.append(rpm_url_list[index]) elif index % 4 == 1:
rpm_url_group_1.append(rpm_url_list[index]) elif index % 4 == 2:
rpm_url_group_2.append(rpm_url_list[index]) elif index % 4 == 3:
rpm_url_group_3.append(rpm_url_list[index])
rpm_url_groups = [rpm_url_group_0, rpm_url_group_1, rpm_url_group_2, rpm_url_group_3] for each_rpm_group in rpm_url_groups:
each_process = multiprocessing.Process(target = multi_thread, args = (each_rpm_group,))
process.append(each_process) for one_process in process:
one_process.start() for one_process in process:
one_process.join()# for each_url in rpm_url_list:# print '*****the %s rpm begin to download *******' %each_url## commands.getoutput('wget %s' %each_url)
def main():
url = 'https://mirrors.ustc.e.cn/centos/7/os/x86_64/Packages/'
url_paas = 'http://mirrors.ustc.e.cn/centos/7.3.1611/paas/x86_64/openshift-origin/'
url_paas2 ='http://mirrors.ustc.e.cn/fedora/development/26/Server/x86_64/os/Packages/u/'
start_time = time.time()
rpm_list = get_rpm_url_list(url_paas) print multi_process(rpm_list) # print multi_thread(rpm_list)
#print multi_process()
# print multi_thread(rpm_list)
# for index in range(len(rpm_list)):
# print 'rpm_url is:', rpm_list[index]
end_time = time.time() print 'the download time is:', end_time - start_timeprint main()123456789101112131415161718
代碼的功能主要是這樣的:
main()方法中調用get_rpm_url_list(base_url)方法,獲取要下載的每個rpm包的具體的url地址。其中base_url即中科大基礎的鏡像源的地址,比如:http://mirrors.ustc.e.cn/centos/7.3.1611/paas/x86_64/openshift-origin/,這個地址下有幾十個rpm包,get_rpm_url_list方法將每個rpm包的url地址拼出來並返回。
multi_process(rpm_url_list)啟動多進程方法,在該方法中,會調用多線程方法。該方法啟動4個多進程,將上面方法得到的rpm包的url地址進行分組,分成4組,然後每一個組中的rpm包再最後由不同的線程去執行。從而達到了多進程+多線程的配合使用。
代碼還有需要改進的地方,比如多進程啟動的進程個數和rpm包的url地址分組是硬編碼,這個還需要改進,畢竟,不同的機器,適合同時啟動的進程個數是不同的。
⑺ python循環怎麼用多線程去運行
背景:Python腳本:讀取文件中每行,放入列表中;循環讀取列表中的每個元素,並做處理操作。
核心:多線程處理單個for循環函數調用
模塊:threading
第一部分:
:多線程腳本 (該腳本只有兩個線程,t1循環次數<t2)#!/usr/bin/env python#-*- coding: utf8 -*- import sysimport timeimport stringimport threadingimport datetimefileinfo = sys.argv[1] # 讀取文件內容放入列表host_list = []port_list = [] # 定義函數:讀取文件內容放入列表中def CreateList(): f = file(fileinfo,'r') for line in f.readlines(): host_list.append(line.split(' ')[0]) port_list.append(line.split(' ')[1]) return host_list return port_list f.close() # 單線程 循環函數,注釋掉了#def CreateInfo(): # for i in range(0,len(host_list)): # 單線程:直接循環列表# time.sleep(1)# TimeMark = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')# print "The Server's HostName is %-15s and Port is %-4d !!! [%s]" % (host_list[i],int(port_list[i]),TimeMark)# # 定義多線程循環調用函數def MainRange(start,stop): #提供列表index起始位置參數 for i in range(start,stop): time.sleep(1) TimeMark = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') print "The Server's HostName is %-15s and Port is %-4d !!! [%s]" % (host_list[i],int(port_list[i]),TimeMark) # 執行函數,生成列表CreateList()# 列表分割成:兩部分 mid為列表的index中間位置mid = int(len(host_list)/2) # 多線程部分threads = []t1 = threading.Thread(target=MainRange,args=(0,mid))threads.append(t1)t2 = threading.Thread(target=MainRange,args=(mid,len(host_list)))threads.append(t2) for t in threads: t.setDaemon(True) t.start()t.join()print "ok"
以上是腳本內容!!!
----------------------------------------------------------------------
:讀取文件的內容
文件內容:
[root@monitor2 logdb]# cat hostinfo.txt
192.168.10.11 1011
192.168.10.12 1012
192.168.10.13 1013
192.168.10.14 1014
192.168.10.15 1015
192.168.10.16 1016
192.168.10.17 1017
192.168.10.18 1018
192.168.10.19 1019
192.168.10.20 1020
192.168.10.21 1021
192.168.10.22 1022
192.168.10.23 1023
192.168.10.24 1024
192.168.10.25 1025
:輸出結果:
單線程 : 執行腳本:輸出結果:
[root@monitor2 logdb]# ./Threadfor.py hostinfo.txt
The Server's HostName is 192.168.10.10 and Port is 1010 !!! [2017-01-10 14:25:14]
The Server's HostName is 192.168.10.11 and Port is 1011 !!! [2017-01-10 14:25:15]
The Server's HostName is 192.168.10.12 and Port is 1012 !!! [2017-01-10 14:25:16]
.
.
.
The Server's HostName is 192.168.10.25 and Port is 1025 !!! [2017-01-10 14:25:29]
多線程:執行腳本:輸出 結果
[root@monitor2 logdb]# ./Threadfor.py hostinfo.txt
The Server's HostName is 192.168.10.11 and Port is 1011 !!! [2017-01-10 14:51:51]
The Server's HostName is 192.168.10.18 and Port is 1018 !!! [2017-01-10 14:51:51]
The Server's HostName is 192.168.10.12 and Port is 1012 !!! [2017-01-10 14:51:52]
The Server's HostName is 192.168.10.19 and Port is 1019 !!! [2017-01-10 14:51:52]
The Server's HostName is 192.168.10.13 and Port is 1013 !!! [2017-01-10 14:51:53]
The Server's HostName is 192.168.10.20 and Port is 1020 !!! [2017-01-10 14:51:53]
The Server's HostName is 192.168.10.14 and Port is 1014 !!! [2017-01-10 14:51:54]
The Server's HostName is 192.168.10.21 and Port is 1021 !!! [2017-01-10 14:51:54]
The Server's HostName is 192.168.10.15 and Port is 1015 !!! [2017-01-10 14:51:55]
The Server's HostName is 192.168.10.22 and Port is 1022 !!! [2017-01-10 14:51:55]
The Server's HostName is 192.168.10.16 and Port is 1016 !!! [2017-01-10 14:51:56]
The Server's HostName is 192.168.10.23 and Port is 1023 !!! [2017-01-10 14:51:56]
The Server's HostName is 192.168.10.17 and Port is 1017 !!! [2017-01-10 14:51:57]
The Server's HostName is 192.168.10.24 and Port is 1024 !!! [2017-01-10 14:51:57]
The Server's HostName is 192.168.10.25 and Port is 1025 !!! [2017-01-10 14:51:58]
⑻ 請教python如何開啟多線程
可以定義函數把這些代碼放在不同的函數里,然後threading模塊
import threading
th1 = threading.Thread(target=func1, args=(arg1, arg2, ...))
照這樣再定義別的線程,開啟用Thread類的start方法
th1.start(); th2.start(); ...
⑼ Python多線程是什麼意思
多線程能讓你像運行一個獨立的程序一樣運行一段長代碼。這有點像調用子進程(subprocess),不過區別是你調用shu的是一個函數或者一個類,而不是獨立的程序。
程基本上是一個獨立執行流程。單個進程可以由多個線程組成。程序中的每個線程都執行特定的任務。例如,當你在電腦上玩游戲時,比如說國際足聯,整個游戲是一個單一的過程。,但它由幾個線程組成,負責播放音樂、接收用戶的輸入、同步運行對手等。所有這些都是單獨的線程,負責在同一個程序中執行這些不同的任務。
每個進程都有一個始終在運行的線程。這是主線。這個主線程實際上創建子線程對象。子線程也由主線程啟動。
⑽ python多線程的幾種方法
Python進階(二十六)-多線程實現同步的四種方式
臨界資源即那些一次只能被一個線程訪問的資源,典型例子就是列印機,它一次只能被一個程序用來執行列印功能,因為不能多個線程同時操作,而訪問這部分資源的代碼通常稱之為臨界區。
鎖機制
threading的Lock類,用該類的acquire函數進行加鎖,用realease函數進行解鎖
import threadingimport timeclass Num:
def __init__(self):
self.num = 0
self.lock = threading.Lock() def add(self):
self.lock.acquire()#加鎖,鎖住相應的資源
self.num += 1
num = self.num
self.lock.release()#解鎖,離開該資源
return num
n = Num()class jdThread(threading.Thread):
def __init__(self,item):
threading.Thread.__init__(self)
self.item = item def run(self):
time.sleep(2)
value = n.add()#將num加1,並輸出原來的數據和+1之後的數據
print(self.item,value)for item in range(5):
t = jdThread(item)
t.start()
t.join()#使線程一個一個執行
當一個線程調用鎖的acquire()方法獲得鎖時,鎖就進入「locked」狀態。每次只有一個線程可以獲得鎖。如果此時另一個線程試圖獲得這個鎖,該線程就會變為「blocked」狀態,稱為「同步阻塞」(參見多線程的基本概念)。
直到擁有鎖的線程調用鎖的release()方法釋放鎖之後,鎖進入「unlocked」狀態。線程調度程序從處於同步阻塞狀態的線程中選擇一個來獲得鎖,並使得該線程進入運行(running)狀態。
信號量
信號量也提供acquire方法和release方法,每當調用acquire方法的時候,如果內部計數器大於0,則將其減1,如果內部計數器等於0,則會阻塞該線程,知道有線程調用了release方法將內部計數器更新到大於1位置。
import threadingimport timeclass Num:
def __init__(self):
self.num = 0
self.sem = threading.Semaphore(value = 3) #允許最多三個線程同時訪問資源
def add(self):
self.sem.acquire()#內部計數器減1
self.num += 1
num = self.num
self.sem.release()#內部計數器加1
return num
n = Num()class jdThread(threading.Thread):
def __init__(self,item):
threading.Thread.__init__(self)
self.item = item def run(self):
time.sleep(2)
value = n.add()
print(self.item,value)for item in range(100):