paramiko模塊,線程,進程


關於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

互斥鎖同時只允許一個線程更改數據,而信號量可以同時允許一定數量的線程更改數據

待續,還沒有整理完


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM