本節內容
-
主機管理之paramiko模塊學習?
- 進程、與線程區別
- python GIL全局解釋器鎖
- 線程
- 語法
- join
- 線程鎖之Lock\Rlock\信號量
- 將線程變為守護進程
- Event事件
- queue隊列
- 生產者消費者模型
- Queue隊列
- 開發一個線程池
- 進程
- 語法
- 進程間通訊
- 進程池
轉載: http://www.cnblogs.com/alex3714/articles/5230609.html
paramiko模塊學習
SSHClient,用于連接遠程服務器并執行基本命令
基于用戶名密碼連接:
1 import paramiko 2 3 # 創建SSH對象 4 ssh = paramiko.SSHClient() 5 # 允許連接不在know_hosts文件中的主機 6 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 7 # 連接服務器 8 ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', password='123') 9 10 # 執行命令 11 stdin, stdout, stderr = ssh.exec_command('df') 12 # 獲取命令結果 13 result = stdout.read() 14 15 # 關閉連接 16 ssh.close()


import paramikotransport = paramiko.Transport(('hostname', 22)) transport.connect(username='wupeiqi', password='123')ssh = paramiko.SSHClient() ssh._transport = transportstdin, stdout, stderr = ssh.exec_command('df') print stdout.read()transport.close()
基于公鑰密鑰連接:
1 import paramiko 2 3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') 4 5 # 創建SSH對象 6 ssh = paramiko.SSHClient() 7 # 允許連接不在know_hosts文件中的主機 8 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 9 # 連接服務器 10 ssh.connect(hostname='c1.salt.com', port=22, username='wupeiqi', key=private_key) 11 12 # 執行命令 13 stdin, stdout, stderr = ssh.exec_command('df') 14 # 獲取命令結果 15 result = stdout.read() 16 17 # 關閉連接 18 ssh.close()


import paramikoprivate_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')transport = paramiko.Transport(('hostname', 22)) transport.connect(username='wupeiqi', pkey=private_key)ssh = paramiko.SSHClient() ssh._transport = transportstdin, stdout, stderr = ssh.exec_command('df')transport.close()


import paramiko from io import StringIOkey_str = """-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEAq7gLsqYArAFco02/55IgNg0r7NXOtEM3qXpb/dabJ5Uyky/8 NEHhFiQ7deHIRIuTW5Zb0kD6h6EBbVlUMBmwJrC2oSzySLU1w+ZNfH0PE6W6fans H80whhuc/YgP+fjiO+VR/gFcqib8Rll5UfYzf5H8uuOnDeIXGCVgyHQSmt8if1+e 7hn1MVO1Lrm9Fco8ABI7dyv8/ZEwoSfh2C9rGYgA58LT1FkBRkOePbHD43xNfAYC tfLvz6LErMnwdOW4sNMEWWAWv1fsTB35PAm5CazfKzmam9n5IQXhmUNcNvmaZtvP c4f4g59mdsaWNtNaY96UjOfx83Om86gmdkKcnwIDAQABAoIBAQCnDBGFJuv8aA7A ZkBLe+GN815JtOyye7lIS1n2I7En3oImoUWNaJEYwwJ8+LmjxMwDCtAkR0XwbvY+ c+nsKPEtkjb3sAu6I148RmwWsGncSRqUaJrljOypaW9dS+GO4Ujjz3/lw1lrxSUh IqVc0E7kyRW8kP3QCaNBwArYteHreZFFp6XmtKMtXaEA3saJYILxaaXlYkoRi4k8 S2/K8aw3ZMR4tDCOfB4o47JaeiA/e185RK3A+mLn9xTDhTdZqTQpv17/YRPcgmwz zu30fhVXQT/SuI0sO+bzCO4YGoEwoBX718AWhdLJFoFq1B7k2ZEzXTAtjEXQEWm6 01ndU/jhAasdfasdasdfasdfa3eraszxqwefasdfadasdffsFIfAsjQb4HdkmHuC OeJrJOd+CYvdEeqJJNnF6AbHyYHIECkj0Qq1kEfLOEsqzd5nDbtkKBte6M1trbjl HtJ2Yb8w6o/q/6Sbj7wf/cW3LIYEdeVCjScozVcQ9R83ea05J+QOAr4nAoGBAMaq UzLJfLNWZ5Qosmir2oHStFlZpxspax/ln7DlWLW4wPB4YJalSVovF2Buo8hr8X65 lnPiE41M+G0Z7icEXiFyDBFDCtzx0x/RmaBokLathrFtI81UCx4gQPLaSVNMlvQA 539GsubSrO4LpHRNGg/weZ6EqQOXvHvkUkm2bDDJAoGATytFNxen6GtC0ZT3SRQM WYfasdf3xbtuykmnluiofasd2sfmjnljkt7khghmghdasSDFGQfgaFoKfaawoYeH C2XasVUsVviBn8kPSLSVBPX4JUfQmA6h8HsajeVahxN1U9e0nYJ0sYDQFUMTS2t8 RT57+WK/0ONwTWHdu+KnaJECgYEAid/ta8LQC3p82iNAZkpWlGDSD2yb/8rH8NQg 9tjEryFwrbMtfX9qn+8srx06B796U3OjifstjJQNmVI0qNlsJpQK8fPwVxRxbJS/ pMbNICrf3sUa4sZgDOFfkeuSlgACh4cVIozDXlR59Z8Y3CoiW0uObEgvMDIfenAj 98pl3ZkCgYEAj/UCSni0dwX4pnKNPm6LUgiS7QvIgM3H9piyt8aipQuzBi5LUKWw DlQC4Zb73nHgdREtQYYXTu7p27Bl0Gizz1sW2eSgxFU8eTh+ucfVwOXKAXKU5SeI +MbuBfUYQ4if2N/BXn47+/ecf3A4KgB37Le5SbLDddwCNxGlBzbpBa0= -----END RSA PRIVATE KEY-----"""private_key = paramiko.RSAKey(file_obj=StringIO(key_str)) transport = paramiko.Transport(('10.0.1.40', 22)) transport.connect(username='wupeiqi', pkey=private_key)ssh = paramiko.SSHClient() ssh._transport = transportstdin, stdout, stderr = ssh.exec_command('df') result = stdout.read()transport.close()print(result)
?
SFTPClient
用于連接遠程服務器并執行上傳下載
基于用戶名密碼上傳下載
1 import paramiko 2 3 transport = paramiko.Transport(('hostname',22)) 4 transport.connect(username='wupeiqi',password='123') 5 6 sftp = paramiko.SFTPClient.from_transport(transport) 7 # 將location.py 上傳至服務器 /tmp/test.py 8 sftp.put('/tmp/location.py', '/tmp/test.py') 9 # 將remove_path 下載到本地 local_path 10 sftp.get('remove_path', 'local_path') 11 12 transport.close()
基于公鑰密鑰上傳下載
1 import paramiko 2 3 private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa') 4 5 transport = paramiko.Transport(('hostname', 22)) 6 transport.connect(username='wupeiqi', pkey=private_key ) 7 8 sftp = paramiko.SFTPClient.from_transport(transport) 9 # 將location.py 上傳至服務器 /tmp/test.py 10 sftp.put('/tmp/location.py', '/tmp/test.py') 11 # 將remove_path 下載到本地 local_path 12 sftp.get('remove_path', 'local_path') 13 14 transport.close()
?
實例:


#!/usr/bin/env python # -*- coding:utf-8 -*- import paramiko import uuidclass Haproxy(object):def __init__(self):self.host = '172.16.103.191'self.port = 22self.username = 'wupeiqi'self.pwd = '123'self.__k = Nonedef create_file(self):file_name = str(uuid.uuid4())with open(file_name,'w') as f:f.write('sb')return file_namedef run(self):self.connect()self.upload()self.rename()self.close()def connect(self):transport = paramiko.Transport((self.host,self.port))transport.connect(username=self.username,password=self.pwd)self.__transport = transportdef close(self):self.__transport.close()def upload(self):# 連接,上傳file_name = self.create_file()sftp = paramiko.SFTPClient.from_transport(self.__transport)# 將location.py 上傳至服務器 /tmp/test.pysftp.put(file_name, '/home/wupeiqi/tttttttttttt.py')def rename(self):ssh = paramiko.SSHClient()ssh._transport = self.__transport# 執行命令stdin, stdout, stderr = ssh.exec_command('mv /home/wupeiqi/tttttttttttt.py /home/wupeiqi/ooooooooo.py')# 獲取命令結果result = stdout.read()ha = Haproxy() ha.run()Demo
?
?
進程與線程
什么是進程(process)?
程序并不能單獨運行,只有將程序裝載到內存中,系統為它分配資源才能運行,而這種執行的程序就稱之為進程。程序和進程的區別就在于:程序是指令的集合,它是進程運行的靜態描述文本;進程是程序的一次執行活動,屬于動態概念。
在多道編程中,我們允許多個程序同時加載到內存中,在操作系統的調度下,可以實現并發地執行。這是這樣的設計,大大提高了CPU的利用率。進程的出現讓每個用戶感覺到自己獨享CPU,因此,進程就是為了在CPU上實現多道編程而提出的。
有了進程為什么還要線程?
進程有很多優點,它提供了多道編程,讓我們感覺我們每個人都擁有自己的CPU和其他資源,可以提高計算機的利用率。很多人就不理解了,既然進程這么優秀,為什么還要線程呢?其實,仔細觀察就會發現進程還是有很多缺陷的,主要體現在兩點上:
-
進程只能在一個時間干一件事,如果想同時干兩件事或多件事,進程就無能為力了。
-
進程在執行的過程中如果阻塞,例如等待輸入,整個進程就會掛起,即使進程中有些工作不依賴于輸入的數據,也將無法執行。
?
例如,我們在使用qq聊天, qq做為一個獨立進程如果同一時間只能干一件事,那他如何實現在同一時刻 即能監聽鍵盤輸入、又能監聽其它人給你發的消息、同時還能把別人發的消息顯示在屏幕上呢?你會說,操作系統不是有分時么?但我的親,分時是指在不同進程間的分時呀, 即操作系統處理一會你的qq任務,又切換到word文檔任務上了,每個cpu時間片分給你的qq程序時,你的qq還是只能同時干一件事呀。
再直白一點, 一個操作系統就像是一個工廠,工廠里面有很多個生產車間,不同的車間生產不同的產品,每個車間就相當于一個進程,且你的工廠又窮,供電不足,同一時間只能給一個車間供電,為了能讓所有車間都能同時生產,你的工廠的電工只能給不同的車間分時供電,但是輪到你的qq車間時,發現只有一個干活的工人,結果生產效率極低,為了解決這個問題,應該怎么辦呢?。。。。沒錯,你肯定想到了,就是多加幾個工人,讓幾個人工人并行工作,這每個工人,就是線程!
?
什么是線程(thread)?
線程是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以并發多個線程,每條線程并行執行不同的任務
?
總結:
進程: qq 要以一個整體的形式暴露給操作系統管理,里面包含對各種資源的調用,內存的管理,網絡接口的調用等。。。
對各種資源管理的集合 就可以成為 進程
線程: 是操作系統最小的調度單位, 是一串指令的集合
?
進程與線程的區別?
1-線程共享內存空間,進程的內存是獨立的
2-同一個進程的線程之間可以直接交流,兩個進程想通信,必須通過一個中間代理來實現
3-創建新線程很簡單, 創建新進程需要對其父進程進行一次克隆
4-一個線程可以控制和操作同一進程里的其他線程,但是進程只能操作子進程
?
Python threading模塊
1-線程的調用
2-join:等待運行結束
setDaemon:守護進程
3-線程鎖(互斥鎖Mutex)
4-Semaphore(信號量):允許最大允許線程數
5-Events
事件是一個簡單的同步對象;
該事件表示一個內部標志和線程
可以等待標志設置,或設置或清除標志本身。
event = threading.Event()
#客戶端線程可以等待標志被設置
event.wait()
一個服務器線程可以設置或重置它
event.set()
event.clear()
如果設置了該標志,則wait方法不會執行任何操作。
如果標志被清除,等待將阻塞,直到它再次設置。
任何數量的線程可能會等待相同的事件。
通過Event來實現兩個或多個線程間的交互,下面是一個紅綠燈的例子,即起動一個線程做交通指揮燈,生成幾個線程做車輛,車輛行駛按紅燈停,綠燈行的規則。
1 import threading,time 2 import random 3 def light(): 4 if not event.isSet(): 5 event.set() #wait就不阻塞 #綠燈狀態 6 count = 0 7 while True: 8 if count < 10: 9 print('\033[42;1m--green light on---\033[0m') 10 elif count <13: 11 print('\033[43;1m--yellow light on---\033[0m') 12 elif count <20: 13 if event.isSet(): 14 event.clear() 15 print('\033[41;1m--red light on---\033[0m') 16 else: 17 count = 0 18 event.set() #打開綠燈 19 time.sleep(1) 20 count +=1 21 def car(n): 22 while 1: 23 time.sleep(random.randrange(10)) 24 if event.isSet(): #綠燈 25 print("car [%s] is running.." % n) 26 else: 27 print("car [%s] is waiting for the red light.." %n) 28 if __name__ == '__main__': 29 event = threading.Event() 30 Light = threading.Thread(target=light) 31 Light.start() 32 for i in range(3): 33 t = threading.Thread(target=car,args=(i,)) 34 t.start()
?
queue隊列?
作用:
1-解耦,使程序直接實現松耦合
2-提高處理效率
class?queue.
Queue
(maxsize=0) #先入先出
- class?
queue.
LifoQueue
(maxsize=0) #last in fisrt out?class?queue.
PriorityQueue
(maxsize=0) #存儲數據時可設置優先級的隊列

1 import queue 2 3 q = queue.PriorityQueue() 4 5 q.put((-1,"A")) 6 q.put((3,"B")) 7 q.put((10,"C")) 8 q.put((6,"A1")) 9 10 print(q.get()) 11 print(q.get()) 12 print(q.get()) 13 print(q.get())
?
生產者消費者模型
在并發編程中使用生產者和消費者模式能夠解決絕大多數并發問題。該模式通過平衡生產線程和消費線程的工作能力來提高程序的整體處理數據的速度。
為什么要使用生產者和消費者模式
在線程世界里,生產者就是生產數據的線程,消費者就是消費數據的線程。在多線程開發當中,如果生產者處理速度很快,而消費者處理速度很慢,那么生產者就必須等待消費者處理完,才能繼續生產數據。同樣的道理,如果消費者的處理能力大于生產者,那么消費者就必須等待生產者。為了解決這個問題于是引入了生產者和消費者模式。
什么是生產者消費者模式
生產者消費者模式是通過一個容器來解決生產者和消費者的強耦合問題。生產者和消費者彼此之間不直接通訊,而通過阻塞隊列來進行通訊,所以生產者生產完數據之后不用等待消費者處理,直接扔給阻塞隊列,消費者不找生產者要數據,而是直接從阻塞隊列里取,阻塞隊列就相當于一個緩沖區,平衡了生產者和消費者的處理能力。
?
下面來學習一個最基本的生產者消費者模型的例子


1 import threading,time 2 3 import queue 4 5 q = queue.Queue(maxsize=10) 6 7 def Producer(name): 8 count = 1 9 while True: 10 q.put("骨頭%s" % count) 11 print("生產了骨頭",count) 12 count +=1 13 time.sleep(0.1) 14 15 16 17 def Consumer(name): 18 #while q.qsize()>0: 19 while True: 20 print("[%s] 取到[%s] 并且吃了它..." %(name, q.get())) 21 time.sleep(1) 22 23 24 25 p = threading.Thread(target=Producer,args=("A1",)) 26 c = threading.Thread(target=Consumer,args=("q1",)) 27 c1 = threading.Thread(target=Consumer,args=("q2",)) 28 29 30 p.start() 31 c.start() 32 c1.start()
?
1 import time,random 2 import queue,threading 3 q = queue.Queue()#線程的queue,實例化 4 def Producer(name): 5 count = 0 6 while count <20: 7 time.sleep(random.randrange(3)) 8 q.put(count) 9 print('Producer %s has produced %s baozi..' %(name, count)) 10 count +=1 11 def Consumer(name): 12 count = 0 13 while count <20: 14 time.sleep(random.randrange(4)) 15 if not q.empty(): 16 data = q.get() 17 print(data) 18 print('\033[32;1mConsumer %s has eat %s baozi...\033[0m' %(name, data)) 19 else: 20 print("-----no baozi anymore----") 21 count +=1 22 p1 = threading.Thread(target=Producer, args=('A',)) 23 c1 = threading.Thread(target=Consumer, args=('B',)) 24 p1.start() 25 c1.start()
?
多進程multiprocessing
多進程是一個使用類似于線程模塊的API來支持產卵過程的包。 多處理包提供本地和遠程并發,通過使用子進程而不是線程來有效地側移全局解釋器鎖。 因此,多處理模塊允許程序員充分利用給定機器上的多個處理器。
進程間通訊
不同進程間內存是不共享的,要想實現兩個進程間的數據交換,可以用以下方法:
Queues
使用方法跟threading里的queue差不多
1 from multiprocessing import Process, Queue 2 3 def f(q): 4 q.put([42, None, 'hello']) 5 6 if __name__ == '__main__': 7 q = Queue() 8 p = Process(target=f, args=(q,)) 9 p.start() 10 print(q.get()) # prints "[42, None, 'hello']" 11 p.join()
?
進程數據共享
進程各自持有一份數據,默認無法共享數據
1 from multiprocessing import Process, Manager 2 3 def f(d, l): 4 d[1] = '1' 5 d['2']=2 6 d[3]=None 7 l.append(1) 8 print(l) 9 10 11 if __name__ == '__main__': 12 with Manager() as manager: 13 d = manager.dict() 14 15 l = manager.list(range(5)) 16 p_list = [] 17 for i in range(3): 18 p = Process(target=f, args=(d, l)) 19 p.start() 20 p_list.append(p) 21 for res in p_list: 22 res.join() 23 print(d)#{1: '1', 3: None, '2': 2} 24 print(l)#[0, 1, 2, 3, 4, 1, 1, 1]
進程同步-進程鎖
當創建進程時(非使用時),共享數據會被拿到子進程中,當進程中執行完畢后,再賦值給原值。


1 from multiprocessing import Process, Lock 2 3 4 def f(l, i): 5 l.acquire() 6 print('hello world', i) 7 l.release() 8 9 10 if __name__ == '__main__': 11 lock = Lock() 12 13 for num in range(100): 14 Process(target=f, args=(lock, num)).start()
?
進程池
進程池內部維護一個進程序列,當使用時,則去進程池中獲取一個進程,如果進程池序列中沒有可供使用的進進程,那么程序就會等待,直到進程池中有可用進程為止。
進程池中有兩個方法:
- apply
- apply_async


1 from multiprocessing import Process, Pool,freeze_support 2 import time 3 import os 4 5 def Foo(i): 6 time.sleep(2) 7 print("in process",os.getpid()) 8 return i + 100 9 10 def Bar(arg): 11 print('-->exec done:', arg,os.getpid()) 12 13 if __name__ == '__main__': 14 #freeze_support()#windows下的要加 15 pool = Pool(processes=3) #允許進程池同時放入3個進程 16 print("主進程",os.getpid()) 17 for i in range(7): 18 pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback回調,調用bar方法 19 #pool.apply(func=Foo, args=(i,)) #串行 20 #pool.apply_async(func=Foo, args=(i,)) #串行,非阻塞時運行 21 print('end') 22 pool.close()#一定要加上 23 pool.join() #進程池中進程執行完畢后再關閉,如果注釋,那么程序直接關閉。.join()
?