【记录】python多线程的使用 线程同步(LOCK和RLOCK) python与mysql数据库交互实现增加和查找 python的格式化输出
文章目錄
- 多線程:
- _thread模塊
- threading模塊:
- 線程同步(LOCK和RLOCK)
- 和mysql交互:
- 附:python的格式化輸出
- 附錄
多線程:
_thread模塊
例一
import _threadimport time# 為線程定義一個函數def print_time(threadName, delay):count = 0while count < 5:time.sleep(delay)count += 1print("%s: %s" % (threadName, time.ctime(time.time())))# 創建兩個線程try:_thread.start_new_thread(print_time, ("Thread-1", 2,))_thread.start_new_thread(print_time, ("Thread-2", 4,))except:print("Error: 無法啟動線程")while 1:pass例二:
import _thread from time import sleep from datetime import datetimedate_time_format='%y-%M-%d %H:%M:%S'def date_time_str(date_time):return datetime.strftime(date_time, date_time_format)def loop_one():print(f'+++線程一開始于:{date_time_str(datetime.now())}')print('+++線程一休眠4秒')sleep(4)print(f'+++線程一休眠結束,結束于:{date_time_str(datetime.now())}')def loop_two():print(f'***線程二開始時間:{date_time_str(datetime.now())}')print('***線程二休眠2秒')sleep(2)print(f'***線程二休眠結束,結束時間:{date_time_str(datetime.now())}')def main():print(f'------所有線程開始時間:{date_time_str(datetime.now())}')_thread.start_new_thread(loop_one, ())_thread.start_new_thread(loop_two, ())sleep(6)print(f'------所有線程結束時間:{date_time_str(datetime.now())}')if __name__ == '__main__':main()
主線程一旦運行結束,就關閉運行著的其他兩個線程。這可能造成主線程過早或過晚退出,這時就要使用線程鎖,主線程可以在兩個子線程都退出后立即退出。 示例代碼如下
threading模塊:
_thread模塊不支持守護線程,當主線程退出時,所有子線程無論是否在工作,都會被強行退出。threading模塊支持守護線程,守護線程一般是一個等待客戶請求的服務器,如果沒有客戶提出請求,就一直等著。如果設定一個線程為守護線程,就表示這個線程不重要,在進程退出時,不用等待這個線程退出。如果主線程退出時不用等待子線程完成,就要設定這些線程的daemon屬性,即在線程Thread.start()開始前,調用setDaemon()函數設定線程的daemon標志(Thread.setDaemon(True)),表示這個線程“不重要”。如果一定要等待子線程執行完成再退出主線程,就什么都不用做或顯式調用Thread.setDaemon(False)以保證daemon標志為False,可以調用Thread.isDaemon()函數判斷daemon標志的值。新的子線程會繼承父線程的daemon標志,主線程在所有非守護線程退出后才會結束,即進程中沒有非守護線程存在時才結束。例子:
import threading from time import sleep from datetime import datetimeloops=[4, 2] date_time_format='%y-%M-%d %H:%M:%S'def date_time_str(date_time):return datetime.strftime(date_time, date_time_format)def loop(n_loop, n_sec):print(f'線程({n_loop})開始執行:{date_time_str(datetime.now())},先休眠({n_sec})秒')sleep(n_sec)print(f'線程({n_loop})休眠結束,結束于:{date_time_str(datetime.now())}') def main():print(f'---所有線程開始執行:{date_time_str(datetime.now())}')threads=[]n_loops=range(len(loops))for i in n_loops:t=threading.Thread(target=loop, args=(i, loops[i]))threads.append(t)for i in n_loops: # start threadsthreads[i].start()for i in n_loops: # wait for allthreads[i].join() # threads to finishprint(f'---所有線程執行結束于:{date_time_str(datetime.now())}')if __name__ == '__main__':main()
附自己修改后的代碼:
線程同步(LOCK和RLOCK)
如果多個線程共同修改某個數據,就可能會出現不可預料的結果。為了保證數據的正確性,需要對多個線程進行同步。 使用Thread對象的Lock和RLock可以實現簡單的線程同步,這兩個對象都有acquire方法和release方法。對于每次只允許一個線程操作的數據,可以將操作放到acquire和release方法之間。 多線程的優勢在于可以同時運行多個任務,但當線程需要共享數據時,可能存在數據不同步的問題。 考慮這樣一種情況:一個列表里所有元素都是0,線程set從后向前把所有元素改成1,而線程print負責從前往后讀取列表并輸出。
線程set開始改的時候,線程print可能就來輸出列表了,輸出就成了一半0一半1,這就是數據不同步的問題。為了避免這種情況,引入了鎖的概念。 鎖有兩種狀態——鎖定和未鎖定。當一個線程(如set)要訪問共享數據時,必須先獲得鎖定;如果已經有別的線程(如print)獲得鎖定了,就讓線程set暫停,也就是同步阻塞;等到線程print訪問完畢,釋放鎖以后,再讓線程set繼續。 經過這樣的處理,輸出列表時要么全部輸出0,要么全部輸出1,不會再出現一半0一半1的尷尬場面。
示例代碼:
import threading from time import sleep from datetime import datetimedate_time_format='%y-%M-%d %H:%M:%S'class MyThread (threading.Thread):def __init__(self, threadID, name, counter):threading.Thread.__init__(self)self.threadID=threadIDself.name=nameself.counter=counterdef run(self):print(f"開啟線程: {self.name}")# 獲取鎖,用于線程同步threadLock.acquire()print_time(self.name, self.counter, 3)# 釋放鎖,開啟下一個線程threadLock.release()def date_time_str(date_time):return datetime.strftime(date_time, date_time_format)def print_time(threadName, delay, counter):while counter:sleep(delay)print(f"{threadName}: {date_time_str(datetime.now())}")counter -= 1def main():# 創建新線程thread1=MyThread(1, "Thread-1", 1)thread2=MyThread(2, "Thread-2", 2)# 開啟新線程thread1.start()thread2.start()# 添加線程到線程列表threads.append(thread1)threads.append(thread2)# 等待所有線程完成for t in threads:t.join()print("退出主線程")if __name__ == "__main__":threadLock=threading.Lock()threads=[]main()和mysql交互:
增加和查詢操作:
import pymysql import time pymysql.install_as_MySQLdb() from sqlalchemy import create_engine,text #定義數據庫屬性 hostname = '127.0.0.1' port = '3308' database = 'data1' username = 'heziyi' pwd = '123456' dburl = 'mysql+mysqldb://{}:{}@{}:{}/{}'.format(username,pwd,hostname,port,database) timenow= time.strftime('%Y-%m-%d',time.localtime(time.time())) print(timenow) #創建數據庫連接對象 engine = create_engine(dburl,echo=True) with engine.connect() as con:# rs = con.execute('SELECT 1') # con.execute(text("select 1 "))sql = 'INSERT INTO data1.wash VALUES(10,\'15\',\'175\',\'9\',\'19.4\',\'2021-05-24\');'result = con.execute( sql)result = con.execute('select * from wash')print(result.fetchall())
查詢某一列:
結果:
[(‘4’, 30.5, datetime.date(2021, 5, 18)), (‘5’, 28.4, datetime.date(2021, 5, 20)), (‘6’, 26.7, datetime.date(2021, 5, 21)), (‘7’, 26.0, datetime.date(2021, 5, 22)), (‘8’, 25.7, datetime.date(2021, 5, 23)), (‘9’, 19.4, datetime.date(2021, 5, 24))]
格式化插入(傳入變量的方式):
timenow= time.strftime('%Y-%m-%d',time.localtime(time.time()))#創建數據庫連接對象 engine = create_engine(dburl,echo=True) with engine.connect() as con:sql = 'INSERT INTO data1.wash VALUES(11,\'15\',\'175\',\'9\',\'19.4\',\'{}\');'.format(timenow)附:python的格式化輸出
多個格式化
‘b’ - 二進制。將數字以2為基數進行輸出。
‘c’ - 字符。在打印之前將整數轉換成對應的Unicode字符串。
‘d’ - 十進制整數。將數字以10為基數進行輸出。
‘o’ - 八進制。將數字以8為基數進行輸出。
‘x’ - 十六進制。將數字以16為基數進行輸出,9以上的位數用小寫字母。
‘e’ - 冪符號。用科學計數法打印數字。用’e’表示冪。
‘g’ - 一般格式。將數值以fixed-point格式輸出。當數值特別大的時候,用冪形式打印。
‘n’ - 數字。當值為整數時和’d’相同,值為浮點數時和’g’相同。不同的是它會根據區域設置插入數字分隔符。
‘%’ - 百分數。將數值乘以100然后以fixed-point(‘f’)格式打印,值后面會有一個百分號。
name = ‘jack’
age = 18
sex = ‘man’
job = “IT”
salary = 9999.99
print(f’my name is {name.capitalize()}.’)
print(f’I am {age:*^10} years old.’)
print(f’I am a {sex}’)
print(f’My salary is {salary:10.3f}’)
結果
my name is Jack.
I am 18 years old.
I am a man
My salary is 9999.990
附錄
關于python運行多線程的問題:
1)Python多線程的效率怎么樣?
答:Python有全鎖局的存在(同一時間只能有一個線程執行),并不能利用多核優勢。如果你的多線程進程是CPU密集型的,多線程就不能帶來效率的提升,相反還可能因為線程的頻繁切換導致效率下降。如果是IO密集型,多線程進程就可以利用IO阻塞等待時的空閑時間執行其他線程,從而提升效率。 (2)既然Python解釋器是單線程的,還有進行多線程編程的必要嗎?
答:多線程最開始不是用來解決多核利用率問題的,而是用來解決IO占用時CPU閑置的問題。 多線程可以用來解決阻塞問題,可以做事件響應機制(或者類似信號槽的問題)。如果運行瓶頸不是在CPU運算而是在IO(網絡)上,多線程顯然很劃算。 能產生IO阻塞的情況很多,如網絡、磁盤等。當發生阻塞時,Python是不耗CPU的,此時如果只有一個線程就沒法處理其他事情了。對于有IO阻塞的環境,多線程可能讓你的CPU跑到100%。 另一個用處來自于Python的C擴展模塊。在擴展模塊里可以釋放GIL。釋放GIL期間不應該調用任何Python API。對于一些非常繁重的計算,可以寫成C模塊,計算前釋放GIL,計算后重新申請GIL,并將結果返回給Python。這樣就可以讓Python進程利用更多CPU資源。每個Python線程都是OS級別的Pthread線程。利用Python管理這些線程比在C層級操作Pthread更方便。
總結
以上是生活随笔為你收集整理的【记录】python多线程的使用 线程同步(LOCK和RLOCK) python与mysql数据库交互实现增加和查找 python的格式化输出的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【算法】广度遍历算法的应用 求出距离顶点
- 下一篇: linux cmake编译源码,linu