關於paramiko模塊
paramiko是基於Python實現的ssh2遠程安全連接,支持認證及密鑰方式遠程執行命令、文件傳輸,中間ssh代理等
paramiko的安裝:
安裝好之后,用paramiko模塊寫一個簡單的遠程ssh運行命令,代碼如下:
1 import paramiko 2 ssh = paramiko.SSHClient() 3 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 4 ssh.connect("192.168.1.23",22,username="root",password="123456") 5 stdin,stdout,stderr = ssh.exec_command("df -h") 6 result = stdout.read() 7 print(result.decode())
運行結果如下:
1 D:\python35\python.exe D:/python培訓/s14/day9/ssh例子.py 2 Filesystem Size Used Avail Use% Mounted on 3 /dev/sda3 77G 1.6G 72G 3% / 4 tmpfs 495M 0 495M 0% /dev/shm 5 /dev/sda1 190M 36M 145M 20% /boot 6 7 8 Process finished with exit code 0
paramiko的核心組件:
SSHClient類,SFTPClient類
a. SSHClient類是一個SSH服務會話的高級表示,該類封裝了傳輸(transport),通道(channel)及SFTPClient的校驗,建立的方法,通常用於執行遠程命令
connect方法
connect(self, hostkey=None, username='', password=None, pkey=None,gss_host=None, gss_auth=False, gss_kex=False, gss_deleg_creds=True)
參數說明:
hostname(str類型):連接的目標主機地址
port(int類型):連接目標主機的端口,默認為22
username(str類型):用戶名
password(str類型):密碼
pkey(PKey類型):私鑰方式,用於身份驗證
gass_host(str類型): The target's name in the kerberos database. Default: hostname
gss_auth(布爾類型):是否使用GSS-API認證
ss_kex=False(布爾類型):是否將GSS-API key和用戶認證交換
gss_deleg_creds(布爾類型):是否代表包含GSS-API 客戶端的憑據
exec_command方法:
遠程執行命令方法,該命令的輸入與輸入流為標准輸入(stdin)、輸出(stdout)、錯誤(stderr)
load_system_host_keys方法
load_host_keys(self, filename)
加載本地總要校驗文件,默認為~/.ssh/known_hosts,非默認另需要手工指定。
參數:
filename(str類型)指定遠程主機公鑰記錄文件
set_missing_host_key_policy方法:
set_missing_host_key_policy(self, policy)
設置連接的遠程主機沒有本地主機秘鑰或HostKeys對象時的策略,目前支持三種,分別是:AutoAddPolicy、RejectPolicy(默認)、WarningPolicy,三者的含義如下:
AutoAddPolicy:自動添加主機名及主機秘鑰到本地HostKeys對象,並將其保存,不依賴load_system_host_keys()的配置,即使~/.ssh/known_hosts不存在也不產生影響
RejectPolicy:自動拒絕位置的主機名和秘鑰,依賴load_system_host_keys()的配置
WarningPolicy:用於記錄一個位置的主機秘鑰的python警告,並接受它,功能上與AutoAddPolicy相似,但未知主機會有警告
b. SFTPClient類
SFTPClient根據SSH傳輸協議的sftp命令會話,實現遠程文件操作:文件的上傳、下載、權限、狀態等操作。
from_transport方法:
from_transport(cls, t, window_size=None, max_packet_size=None)
參數說明:
t:一個已經通過驗證的傳輸對象
例子:
1 transport = paramiko.Transport(('192.168.1.23',22)) 2 transport.connect(username="root",password="123456") 3 sftp = paramiko.SFTPClient.from_transport(transport)
put方法:
長傳本地文件到遠程SFTP服務端
put(self, localpath, remotepath, callback=None, confirm=True)
參數說明:
localpath(str類型):需要上傳的本地文件(源文件)
remotepath(str類型):遠程路徑(目標文件)
callback(function(init,init)):獲取已接收的字節數及總傳輸字節數,以便回調函數調用,默認為None
confirm(bool類型):文件長傳完畢后是否調用start()方法,以便確認文件的大小
get方法
get(self, remotepath, localpath, callback=None)
從遠程SFTP服務端下載本地
參數說明:
remotepath(str類型):需要下載的遠程文件
localpath(str類型):本地路徑
callback(function(init,init)): 獲取已接收的字節數及總傳輸字節數,以便回調函數調用,默認為None
其他方法:
SFTPClient類其他常用方法:
Mkdir:在SFTP服務端創建目錄
remove:刪除SFTP服務端指定目錄
rename:重命名SFTP服務端文件或目錄
stat:獲取遠程SFTP服務端指定文件的信息
listdir:獲取遠程SFTP服務端指定目錄列表,以Python的列表形式返回
下面是實際的代碼例子:
基於賬戶名和密碼的上傳和下載文件
#AUTHOR:FAN
import paramiko
#t就相當於創建通道
t = paramiko.Transport(("192.168.1.23",22))
t.connect(username="root",password="123456")
#這里表示sftp通過t這個通道傳輸數據
sftp = paramiko.SFTPClient.from_transport(t)
#sftp.put("ssh例子.py","/tmp/aaa.py")
sftp.get("/tmp/aaa.py","sss")
sftp.close()
同樣的也可以通過基於公鑰的上傳和下載文件
進程與線程
1、 線程:是操作系統能夠進行運算的調度的最小單位,它被包含在進程中,是進程中實際的運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程可以並發多個線程,每條線程並行執行不同的任務。
線程是一串指令的集合
2、 進程:程序要以一個整體的形式暴露給操作系統管理,里面包含對各種資源的調用,內存的管理,網絡接口的調用等….即對各種資源的集合。
進程要操作cpu,必須要先創建一個線程
所有在同一個進程里的線程是共享同一塊內存空間的
線程共享內存空間,進程的內存是獨立的
同一個進程的線程之間可以直接交流,兩個進程想要通信,必須通過一個中間代理來實現
創建新線程很簡單,創建新進程需要對其父進程進行一次克隆
一個線程可以控制和操作同一個進程里的其他線程,但是進程只能操作子進程
一個最簡單的多線程的代碼例子:
1 import threading,time 2 def run(n): 3 print("task",n) 4 time.sleep(2) 5 6 t1 = threading.Thread(target=run,args=("t1",)) 7 t2 = threading.Thread(target=run,args=("t2",)) 8 t1.start() 9 t2.start()
下面是一個對多線程的一個處理方法:(需要理解):
1 import threading 2 import time 3 def run(n): 4 print("task:",n) 5 time.sleep(2) 6 print("task done:",n) 7 8 start_time = time.time() 9 for i in range(10): 10 t = threading.Thread(target=run,args=(i,)) 11 t.start() 12 print("cost:",time.time()-start_time)
運行結果如下:
1 D:\python35\python.exe D:/python培訓/s14/day9/threading_ex2.py 2 task: 0 3 task: 1 4 task: 2 5 task: 3 6 task: 4 7 task: 5 8 task: 6 9 task: 7 10 task: 8 11 task: 9 12 cost: 0.0010001659393310547 13 task done: 1 14 task done: 2 15 task done: 4 16 task done: 0 17 task done: 5 18 task done: 9 19 task done: 8 20 task done: 6 21 task done: 3 22 task done: 7 23 24 Process finished with exit code 0 25 下圖是對上述程序的理解,這個非常重要,之前自己一直迷糊在這個地方
下圖是對上述程序的理解,這個非常重要,之前自己一直迷糊在這個地方
但是現在有個問題,我們需要計算所有線程的執行時間,並且讓所有線程運行之后再運行主程序
這里就需要用到線程里的一個方法join()意思其實就是等待的意思代碼如下:
1 import threading 2 import time 3 def run(n): 4 print("task:",n) 5 time.sleep(2) 6 print("task done:",n) 7 8 start_time = time.time() 9 t_obj = [] 10 for i in range(10): 11 t = threading.Thread(target=run,args=(i,)) 12 t.start() 13 t_obj.append(t) 14 for i in t_obj: 15 i.join() 16 17 print("all thread is done") 18 print("cost:",time.time()-start_time)
threading.current_thread() 表示當前線程
threading.active_count() 表示當前活躍線程數
關於守護線程
如果將線程設置為守護線程,則主程序不會管線程是否執行完,只有主程序執行完畢之后,就會結束
代碼例子如下:
1 #AUTHOR:FAN 2 3 import threading 4 import time 5 def run(n): 6 print("task:",n) 7 time.sleep(2) 8 print("task done:",n) 9 10 start_time = time.time() 11 for i in range(10): 12 t = threading.Thread(target=run,args=(i,)) 13 t.setDaemon(True) 14 t.start() 15 16 print("all thread is done",threading.current_thread(),threading.active_count()) 17 print("cost:",time.time()-start_time)
運行結果如下:
1 D:\python35\python.exe D:/python培訓/s14/day9/threading_ex2.py 2 task: 0 3 task: 1 4 task: 2 5 task: 3 6 task: 4 7 task: 5 8 task: 6 9 task: 7 10 task: 8 11 task: 9 12 all thread is done <_MainThread(MainThread, started 5908)> 11 13 cost: 0.007000446319580078 14 15 Process finished with exit code 0
GIL 全局解釋器鎖
無論你啟多少個線程,你有多少個cpu, Python在執行的時候會淡定的在同一時刻只允許一個線程運行
線程鎖(互斥鎖)
一個進程下可以啟動多個線程,多個線程共享父進程的內存空間,這樣每個線程可以訪問同一份數據,此時如果多個線程同時修改一份數據,就會出現問題。
但是經過測試在3.0上不存在這個問題
遞歸鎖
也就是鎖中包含鎖,代碼例子:
1 import threading,time 2 3 def run1(): 4 print("grab the first part data") 5 lock.acquire() 6 global num 7 num +=1 8 lock.release() 9 return num 10 def run2(): 11 print("grab the second part data") 12 lock.acquire() 13 global num2 14 num2+=1 15 lock.release() 16 return num2 17 def run3(): 18 lock.acquire() 19 res = run1() 20 print('--------between run1 and run2-----') 21 res2 = run2() 22 lock.release() 23 print(res,res2) 24 25 26 if __name__ == '__main__': 27 28 num,num2 = 0,0 29 lock = threading.RLock() 30 for i in range(10): 31 t = threading.Thread(target=run3) 32 t.start() 33 34 while threading.active_count() != 1: 35 print(threading.active_count()) 36 else: 37 print('----all threads done---') 38 print(num,num2)
信號量semaphore
互斥鎖同時只允許一個線程更改數據,而信號量可以同時允許一定數量的線程更改數據
待續,還沒有整理完