Python Day9

發布時間:2019-08-13 07:41:24編輯:auto閱讀(149)

    基于udp協議的套接字

    s.recvfrom() 接收UDP數據
    s.sendto() 發送UDP數據

    UDP(user datagram protocol,用戶數據報協議)是無連接的,面向消息的,提供高效率服務。
    不會使用塊的合并優化算法, 由于UDP支持的是一對多的模式,所以接收端的skbuff(套接字緩沖區)采用了鍊式結構來記錄每一個到達的UDP包
    在每個UDP包中就有了消息頭(消息來源地址,端口等信息),這樣,對于接收端來說,就容易進行區分處理了。
    即面向消息的通信是有消息保護邊界的。

    udp的recvfrom是阻塞的,一個recvfrom(x)必須對唯一一個sendinto(y),收完了x個字節的數據就算完成
    若是y>x數據就丢失,這意味着udp根本不會粘包,但是會丢數據,不可靠

    udp是無鍊接的,先啟動哪一端都不會報錯
    udp發送數據,對端是不會返回确認信息的,因此不可靠

    服務端:

    from socket import *
    
    server = socket(AF_INET, SOCK_DGRAM)  #創建一個服務器的套接字
    server.bind(('127.0.0.1', 8080))      #綁定服務器套接字
    
    while True:
        data, client_addr = server.recvfrom(1024)
        server.sendto(data.upper(),client_addr)
    
    server.close()

    客戶端:

    from socket import *
    
    client=socket(AF_INET,SOCK_DGRAM)
    
    while True:
        msg=input('>>: ').strip()
        if not msg:continue
        client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
        data,server_addr=client.recvfrom(1024)
        print(data.decode('utf-8'))
    
    client.close()

    進程

    進程:正在進行的一個過程或者說一個任務。而負責執行任務則是cpu。
    程序僅僅隻是一堆代碼而已,而進程指的是程序的運行過程。

    multiprocessing模塊介紹

    multiprocessing模塊用來開啟子進程,并在子進程中執行我們定制的任務(比如函數),該模塊與多線程模塊threading的編程接口類似。
    與線程不同,進程沒有任何共享狀态,進程修改的數據,改動僅限于該進程内

    Process類的介紹

    創建進程的類:
    Process是一個類
    class Process(object):
    def init(self, group=None, target=None, name=None, args=(), kwargs={}):
    group是保留的,target指定起一個進程要做什麼事,name是指定進程的名字,args和kwargs是為前面任務傳參的方式

    參數介紹:

    args指定的為傳給target函數的位置參數,是一個元組形式,必須有逗号
    group參數未使用,值始終為None
    target表示調用對象,即子進程要執行的任務
    args表示調用對象的位置參數元組,args=(1,2,'egon',)
    kwargs表示調用對象的字典,kwargs={'name':'egon','age':18}
    name為子進程的名稱

    方法介紹:

    p.start():啟動進程,并調用該子進程中的p.run()
    p.run():進程啟動時運行的方法,正是它去調用target指定的函數,我們自定義類的類中一定要實現該方法
    p.terminate():強制終止進程p,不會進行任何清理操作,如果p創建了子進程,該子進程就成了僵屍進程,使用該方法需要特别小心這種情況。如果p還保存了一個鎖那麼也将不會被釋放,進而導緻死鎖
    p.is_alive():如果p仍然運行,返回True
    p.join([timeout]):主線程等待p終止(強調:是主線程處于等的狀态,而p是處于運行的狀态)。timeout是可選的超時時間,需要強調的是,p.join隻能join住start開啟的進程,而不能join住run開啟的進程

    屬性介紹:

    p.daemon:默認值為False,如果設為True,代表p為後台運行的守護進程,當p的父進程終止時,p也随之終止,并且設定為True後,p不能創建自己的新進程,必須在p.start()之前設置
    p.name:進程的名稱
    p.pid:進程的pid
    p.exitcode:進程在運行時為None、如果為–N,表示被信号N結束(了解即可)

    開啟進程的兩種方式

    方式一:

    from multiprocessing import Process
    import time
    
    def task(name):
        print('%s is running' %name)
        time.sleep(3) #模拟任務運行了一段時間後結束
        print('%s is done' %name)
    
    if __name__ == '__main__': #注意,在windows下開進程的代碼必須寫到main下面,這個windows開進程的原理有關
        p=Process(target=task,args=('alex',)) #注意需要加逗号,因為這裡是元祖
        p.start() #上面實例化出一個對象,這個start隻是向操作系統發出一個請求,操作系統會把父進程裡面的數據拷貝到子進程
        print('主')

    結果:

    主
    alex is running
    (等了三秒)
    alex is do

    方式二:
    Process既然是一個類,那我們可以繼承它寫一個自己的類

    from multiprocessing import Process
    import time
    
    class MyProcess(Process):
        def __init__(self,name):
            super(MyProcess,self).__init__()
            self.name=name
    
    注意,自定義類這種方式裡面必須寫一個run方法,實例化後調用的start()實際就是run()方法
        def run(self):  #這個run取代了方式一種的task方法
            print('%s is running' %self.name)
            time.sleep(3) #模拟任務運行了一段時間後結束
            print('%s is done' %self.name)
    
    if __name__ == '__main__':
        p=MyProcess('進程1')
        p.start() #p.start()調用的就是類中的run()
        print('主')

    運行結果與方式一一樣

    join方法

    主進程等待子進程結束

    from multiprocessing import Process
    import time
    import os
    
    def task(n):
        print('%s is running' %os.getpid()) #查看pid
        time.sleep(n)
        print('%s is doen' %os.getpid())
    
    if __name__ == '__main__':
    
        start_time = time.time()
    
        p1 = Process(target=task, args=(1,))
        p2 = Process(target=task, args=(2,))
        p3 = Process(target=task, args=(3,))
    
        p1.start()
        p1.join()    #主線程等待p1終止再執行下面的内容
        p2.start()
        p2.join()    #主線程等待p2終止再執行下面的内容
        p3.start()
        p3.join()    #主線程等待p3終止再執行下面的内容
    
        stop_time = time.time()
    
        print('主', (stop_time - start_time))

    結果:

    is running
    is doen
    is running
    is doen
    is running
    is doen
    主 6.226877450942993

    進程對象的其它屬性或方法

    from multiprocessing import Process
    import os,time
    
    def task():
        print('子進程pid: %s 父進程ppid: %s' %(os.getpid(),os.getppid())) #ppid是父進程pid
    
    if __name__ == '__main__':
        p = Process(target=task,name='進程1')
        p.start()
        #p.terminate() #關閉進程,不會立即關閉,所以is_alive立刻查看的結果可能還是存活
        time.sleep(0.5)
        print('父進程pid: %s' %os.getpid())
        print('子進程pid: %s' %p.pid)  #打印進程pid,跟os.getpid一樣
        print(p.name) #可以打印子進程名稱
        #p.name='xxxx' #也可以直接設置name屬性

    結果:

    子進程pid: 6692 父進程ppid: 7652
    父進程pid: 7652
    子進程pid: 6692
    進程1

    僵屍進程與孤兒進程

    僵屍進程(有害)

    僵屍進程:一個進程使用fork創建子進程,如果子進程退出,而父進程并沒有調用wait或waitpid獲取子進程的狀态信息,那麼子進程的進程描述符仍然保存在系統中。
    這種進程稱之為僵死進程。
    任何一個子進程(init除外)在exit()之後,并非馬上就消失掉,而是留下一個稱為僵屍進程(Zombie)的數據結構,等待父進程處理。
    這是每個子進程在結束時都要經過的階段。

    小知識:
    在linux系統中使用ps命令查看的話,狀态為Z的進程就是僵屍進程 ps aux |grep Z
    使用top命令 zombie代表當前有多少個僵屍進程

    解決方法:

    1. 殺死父進程
    2. 對開啟的子進程應該記得使用join,join會回收僵屍進程,join方法中調用了wait,告訴系統釋放僵屍進程
    3. 使用signal(SIGCHLD, SIG_IGN)處理僵屍進程 http://mqag.caifu85608.cn

    孤兒進程(無害)

    一個父進程退出,而它的一個或多個子進程還在運行,那麼那些子進程将成為孤兒進程。孤兒進程将被init進程(進程号為1)所收養,并由init進程對它們完成狀态收集工作。

    守護進程

    當子進程執行的任務在父進程代碼運行完畢後就沒有存在的必要了,
    那該子進程就應該被設置為守護進程

    守護進程要在子進程開啟前進行設置(再start之前)
    守護進程裡面沒辦法再開子進程

    設置成守護進程後,主進程一旦運行完代碼的最後一行,守護進程就會跟着結束,不會管主進程是否還等待非守護子進程結束

    示例代碼:

    from multiprocessing import Process
    
    import time
    def foo():
        print(123)
        time.sleep(1)
        print("end123")  #這行永遠不可能打印
    
    def bar():
        print(456)
        time.sleep(3)
        print("end456")
    
    if __name__ == '__main__':
    
        p1=Process(target=foo)
        p2=Process(target=bar)
    
        p1.daemon=True
        p1.start()
        p2.start()
        print("main-------") #這行執行結束後p1(守護進程)就會跟着結束

    互斥鎖

    進程之間數據不共享,但是共享同一套文件系統,所以訪問同一個文件,或同一個打印終端,是沒有問題的,
    而共享帶來的是競争,競争帶來的結果就是錯亂,如何控制,就是加鎖處理

    與join的區别
    join是把整體變成了串行,互斥鎖可以隻把需要的地方變成串行

    代碼示例:
    這裡使用搶票進行模拟,進程之間通過文件進行通信,保證隻有一個進程能夠搶到票

    from multiprocessing import Process,Lock
    import json
    import time
    import random
    import os
    
    def search():
        time.sleep(random.random()) #默認(0,1)取大于0且小于1之間的小數
        dic=json.load(open('db.txt','r',encoding='utf-8'))
        print('%s 查看剩餘票數: %s' %(os.getpid(),dic['count']))
    
    def get():
        dic = json.load(open('db.txt', 'r', encoding='utf-8'))
        if dic['count'] > 0:
            dic['count']-=1
            time.sleep(random.randint(1,3))
            json.dump(dic,open('db.txt','w',encoding='utf-8'))
            print('%s 購票成功' %os.getpid())
    
    def task(mutex):
        mutex.acquire() #加鎖
        search()
        get()
        mutex.release() #釋放鎖
        #隻有鎖被釋放後其它進程才能搶到鎖并運行這段代碼
    
            # with mutex:   #另外一種寫法,等同于mutex.acquire()
        #     search()
        #     get()
    
    if __name__ == '__main__':
        mutex = Lock() #實例化一把鎖
        for i in range(10):
            p=Process(target=task,args=(mutex,)) #别忘了args後面要跟一個數組
            p.start()

    總結:

    加鎖可以保證多個進程修改同一塊數據時,同一時間隻能有一個任務可以進行修改,即串行的修改,沒錯,速度是慢了,但犧牲了速度卻保證了數據安全。
    雖然可以用文件共享數據實現進程間通信,但問題是:

    • 效率低(共享數據基于文件,而文件是硬盤上的數據)
    • 需要自己加鎖處理

    因此我們最好找尋一種解決方案能夠兼顧:1、效率高(多個進程共享一塊内存的數據)2、幫我們處理好鎖問題。這就是mutiprocessing模塊為我們提供的基于消息的IPC通信機制:隊列和管道。

    • 隊列和管道都是将數據存放于内存中
    • 隊列又是基于(管道+鎖)實現的,可以讓我們從複雜的鎖問題中解脫出來,
      我們應該盡量避免使用共享數據,盡可能使用消息傳遞和隊列,避免處理複雜的同步和鎖問題,而且在進程數目增多時,往往可以獲得更好的可獲展性。

    隊列

    進程彼此之間互相隔離,要實現進程間通信(IPC),multiprocessing模塊支持兩種形式:隊列和管道,這兩種方式都是使用消息傳遞的

    創建隊列的類(底層就是以管道和鎖定的方式實現):

    Queue([maxsize]):創建共享的進程隊列,Queue是多進程安全的隊列,可以使用Queue實現多進程之間的數據傳遞。

    參數介紹:
    maxsize是隊列中允許最大項數,省略則無大小限制。

    主要方法:

    • q.put方法用以插入數據到隊列中,put方法還有兩個可選參數:blocked和timeout。

      如果blocked為True(默認值),并且timeout為正值,該方法會阻塞timeout指定的時間,直到該隊列有剩餘的空間。
      如果超時,會抛出Queue.Full異常。如果blocked為False,但該Queue已滿,會立即抛出Queue.Full異常。

    • q.get方法可以從隊列讀取并且删除一個元素,get方法有兩個可選參數:blocked和timeout。

      如果blocked為True(默認值),并且timeout為正值,那麼在等待時間内沒有取到任何元素,會抛出Queue.Empty異常。
      如果blocked為False,有兩種情況存在,如果Queue有一個值可用,則立即返回該值,否則,如果隊列為空,則立即抛出Queue.Empty異常.

    示例代碼:

    from multiprocessing import Queue
    
    q=Queue(3)
    
    q.put('first')
    q.put(2)
    q.put({'count':3})
    # q.put('fourth',block=False)           #等同于q.put_nowait('fourth')
    # q.put('fourth',block=True,timeout=3)  #block代表阻塞(blocked)
    
    print(q.get())
    print(q.get())
    print(q.get())
    # print(q.get(block=False)) #等同于q.get_nowait()
    print(q.get(block=True,timeout=3)) #在等待時間内沒有取到任何元素,會抛出Queue.Empty異常

    q.get_nowait():同q.get(False)
    q.put_nowait():同q.put(False)

    生産者消費者模型

    為什麼要使用生産者和消費者模式
    在線程世界裡,生産者就是生産數據的線程,消費者就是消費數據的線程。
    在多線程開發當中,如果生産者處理速度很快,而消費者處理速度很慢,那麼生産者就必須等待消費者處理完,才能繼續生産數據。
    同樣的道理,如果消費者的處理能力大于生産者,那麼消費者就必須等待生産者。為了解決這個問題于是引入了生産者和消費者模式。

    代碼示例

    from multiprocessing import Process,Queue
    import time
    import random
    
    def producer(name,food,q): #生産者
        for i in range(3):
            res='%s%s' %(food,i)
            time.sleep(random.randint(1,3))
            q.put(res)  #生産者把生産的内容放入隊列
            print('廚師[%s]生産了<%s>' %(name,res))
    
    def consumer(name,q):  #消費者
        while True:
            res=q.get()
            if res is None:break  #如果接收到None,則break掉整個循環
            time.sleep(random.randint(1,3))
            print('吃貨[%s]吃了<%s>' % (name, res))
    
    if __name__ == '__main__':
        #隊列
        q=Queue()
        #生産者們
        p1=Process(target=producer,args=('egon1','泔水',q))
    
        #消費者們
        c1=Process(target=consumer,args=('管廷威',q))
    
        p1.start()
        c1.start()
    
        p1.join() #生産者結束運行後執行下面的代碼
        q.put(None) #給隊列中發送一個None
    
        print('主')

    生産者消費者模型總結

    程序中有兩類角色
    一類負責生産數據(生産者)
    一類負責處理數據(消費者)

    引入生産者消費者模型為了解決的問題是:
    平衡生産者與消費者之間的工作能力,從而提高程序整體處理數據的速度

    如何實現:
    生産者<-->隊列<——>消費者
    生産者消費者模型實現類程序的解耦和

    JoinableQueue與守護進程應用

    上面主動向隊列發特定關鍵詞當信号,再讓消費者判斷數據内容的方式很low,因為有幾個消費者就需要發送幾次結束信号。
    multiprocessing模塊提供了類似原理的類JoinableQueue,即等待隊列完成

    JoinableQueue([maxsize]):
    這就像是一個Queue對象,但隊列允許項目的使用者通知生成者項目已經被成功處理。通知進程是使用共享的信号和條件變量來實現的。

    參數介紹:

    maxsize是隊列中允許最大項數,省略則無大小限制。
    方法介紹:
    JoinableQueue的實例p除了與Queue對象相同的方法之外還具有:
    q.task_done():使用者使用此方法發出信号,表示q.get()的返回項目已經被處理。如果調用此方法的次數大于從隊列中删除項目的數量,将引發ValueError異常
    q.join():生産者調用此方法進行阻塞,直到隊列中所有的項目均被處理。阻塞将持續到隊列中的每個項目均調用q.task_done()方法為止

    示例代碼

    from multiprocessing import Process,JoinableQueue
    import time
    import random
    
    def producer(name,food,q):
        for i in range(3):
            res='%s%s' %(food,i)
            time.sleep(random.randint(1,3))
            q.put(res)
            print('廚師[%s]生産了<%s>' %(name,res))
    
    def consumer(name,q):
        while True:
            res=q.get()
            if res is None:break
            time.sleep(random.randint(1,3))
            print('吃貨[%s]吃了<%s>' % (name, res))
            q.task_done() #消費者每消費一個就給q.join()發信号,告訴它管道内的數據少了一個
    
    if __name__ == '__main__':
        #隊列
        q=JoinableQueue()
        #生産者們
        p1=Process(target=producer,args=('egon1','泔水',q))
        p2=Process(target=producer,args=('egon2','骨頭',q))
        #消費者們
        c1=Process(target=consumer,args=('管廷威',q))
        c2=Process(target=consumer,args=('oldboy',q))
        c3=Process(target=consumer,args=('oldgirl',q))
        c1.daemon=True  #把三個消費者都設置成守護進程,主進程結束後跟着結束
        c2.daemon=True  #這裡提供了一個守護進程的應用場景
        c3.daemon=True
    
        p1.start()
        p2.start()
        c1.start()
        c2.start()
        c3.start()
    
        p1.join()
        p2.join()
        #此時生産者已經完成任務,q.join獲取當前管道中的數據數量
        q.join()
        #等管道内數據為0後,執行下一行代碼,這也意味着消費者取走了管道内的所有數據,此時消費者也完成了使命
        print('主')

    線程

    在傳統操作系統中,每個進程有一個地址空間,而且默認就有一個控制線程
    所以,進程隻是用來把資源集中到一起(進程隻是一個資源單位,或者說資源集合),而線程才是cpu上的執行單位
    多線程(即多個控制線程)的概念是,在一個進程中存在多個控制線程,多個控制線程共享該進程的地址空間,相當于一個車間内有多條流水線,都共用一個車間的資源。
    沒有子線程的概念,在一個進程内多個線程是平等的,下文中的“主線程”僅為了區分
    開線程資源消耗小

    http://iugjkg.caifu85608.cn

    開線程的兩種方式

    第一種:

    from threading import Thread
    import time
    import random
    
    def piao(name):
        print('%s is piao start' % name)
        time.sleep(random.randint(1, 3))
        print('%s is piao end' % name)
    
    if __name__ == '__main__':
        t1 = Thread(target=piao, args=('alex',))  # 實例化一個t1線程,args後面是傳參,以元祖形式,所以要有個一個逗号
        t1.start()
        print('主線程')

    第二種(自己寫一個類):

    from threading import Thread
    import time
    import random
    
    class MyThread(Thread):
        def __init__(self, name):  # 在初始化時定制
            super().__init__()  #繼承父類的init
            self.name = name
    
        def run(self):
            print('%s is piao start' % self.name)
            time.sleep(random.randint(1, 3))
            print('%s is piao end' % self.name)
    
    if __name__ == '__main__':
        t1 = MyThread('alex')
        t1.start()  #start執行的就是自定義函數中的run方法
        print('主線程')

    多線程實現并發的套接字通信

    相關内容請參考上一篇文章day8
    服務端:

    from threading import Thread,current_thread
    from socket import *
    
    def comunicate(conn):
        print('子線程:%s' %current_thread().getName()) #查看當前線程名字
        while True:
            try:
                data=conn.recv(1024)
                if not data:break   #針對linux系統,linux系統中客戶端單方便斷開連接,服務端不會報錯會一直收空
                conn.send(data.upper())
            except ConnectionResetError:   #在windows上客戶端單方面斷開鍊接會報錯,這裡将報錯處理掉
                break
        conn.close()
    
    def server(ip,port):
        print('主線程:%s' %current_thread().getName())  #查看當前線程名字
        server = socket(AF_INET, SOCK_STREAM)
        server.bind((ip,port))
        server.listen(5)
    
        while True:
            conn, addr = server.accept()   #主線程負責建立連接,獲得conn
            print(addr)
            # comunicate(conn)
            t=Thread(target=comunicate,args=(conn,))
            t.start()
    
        server.close()
    
    if __name__ == '__main__':
        server('127.0.0.1', 8081)

    客戶端:

    from socket import *
    
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8081))
    
    while True:
        msg=input('>>: ').strip()
        if not msg:continue
        client.send(msg.encode('utf-8'))
        data=client.recv(1024)
        print(data.decode('utf-8'))
    
    client.close()

    這裡有個問題,現在的實現效果意味着每連接一個客戶端都要起一個線程,然而開線程(或進程)是要消耗系統資源的,不能無限開
    這種實現方式是有弊端的,解決辦法要用到池的概念,看後面的文章day10

    線程相關的其他方法

    Thread實例對象的方法

    isAlive(): 返回線程是否活動的
    getName(): 返回線程名
    setName(): 設置線程名

    守護線程

    主線程代表了這個進程的生命周期,進程内所有的線程結束後主線程才能結束
    主線程執行完畢後(運行完最後一行代碼)要等其他線程執行完才能結束
    詳細解釋:

    • 主進程在其代碼結束後就已經算運行完畢了(守護進程在此時就被回收),然後主進程會一直等非守護的子進程都運行完畢後回收子進程的資源(否則會産生僵屍進程),才會結束,

    • 主線程在其他非守護線程運行完畢後才算運行完畢(守護線程在此時就被回收)。因為主線程的結束意味着進程的結束,進程整體的資源都将被回收,而進程必須保證非守護線程都運行完畢後才能結束。

    守護線程在主線程執行完最後一行代碼後立即終止,即守護xxx會等待主xxx運行完畢後被銷毀

    迷惑人的例子

    from threading import Thread
    import time
    def foo():
        print(123)
        time.sleep(1)
        print("end123")
    
    def bar():
        print(456)
        time.sleep(3)
        print("end456")
    
    if __name__ == '__main__':
        t1=Thread(target=foo)
        t2=Thread(target=bar)
    
        t1.daemon=True  #t1是守護線程
        t1.start()
        t2.start()      #t2是非守護線程,主線程要等它結束後才能結束
        print("main-------")

    結果:

    123
    456
    main------- #雖然執行到最後一行代碼了,但t2這個非守護線程還沒結束,主線程要等待
    end123      #等待t2的過程中守護線程t1已經執行完了
    end456

    GIL解釋器鎖

    GIL是CPython解釋器的特性

    在Cpython解釋器中,同一個進程下開啟的多線程,同一時刻隻能有一個線程執行,無法利用多核優勢

    結論:

    多線程用于IO密集型,如socket,爬蟲,web
    多進程用于計算密集型,如金融分析

    paramiko模塊

    paramiko是一個用于做遠程控制的模塊,使用該模塊可以對遠程服務器進行命令或文件操作
    值得一說的是,fabric和ansible内部的遠程管理就是使用的paramiko來現實

    pip3 install paramiko #在python3中安裝

    http://t8vb0nec.caifu85608.cn

    使用

    SSHClient

    用于連接遠程服務器并執行基本命令

    • 基于用戶名密碼連接:

      import paramiko
      
      #創建SSH對象
      ssh = paramiko.SSHClient()
      #允許連接不在know_hosts文件中的主機
      ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      #連接服務器
      ssh.connect(hostname='10.0.0.101', port=22, username='root', password='123456')
      
      #執行命令
      stdin, stdout, stderr = ssh.exec_command('df -h')
      #獲取命令結果
      result = stdout.read()
      print(result.decode('utf-8'))
      #關閉連接
      ssh.close()
    • 基于公鑰密鑰連接:
      客戶端文件名:id_rsa

    服務端必須有文件名:authorized_keys(在用ssh-keygen時,必須制作一個authorized_keys,可以用ssh-copy-id來制作)

    import paramiko
    
    private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa')
    
    #創建SSH對象
    ssh = paramiko.SSHClient()
    #允許連接不在know_hosts文件中的主機
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    #連接服務器
    ssh.connect(hostname='120.92.84.249', port=22, username='root', pkey=private_key)
    
    #執行命令
    stdin, stdout, stderr = ssh.exec_command('df')
    #獲取命令結果
    result = stdout.read()
    print(result.decode('utf-8'))
    #關閉連接
    ssh.close()

    SFTPClient

    用于連接遠程服務器并執行上傳下載

    • 基于用戶名密碼上傳下載
    import paramiko
    
    transport = paramiko.Transport(('120.92.84.249',22))
    transport.connect(username='root',password='xxx')
    
    sftp = paramiko.SFTPClient.from_transport(transport)
    #将location.py 上傳至服務器 /tmp/test.py
    sftp.put('/tmp/id_rsa', '/etc/test.rsa')
    #将remove_path 下載到本地 local_path
    sftp.get('remove_path', 'local_path')
    
    transport.close()
    • 基于公鑰密鑰上傳下載
    import paramiko
    
    private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa')
    
    transport = paramiko.Transport(('120.92.84.249', 22))
    transport.connect(username='root', pkey=private_key )
    
    sftp = paramiko.SFTPClient.from_transport(transport)
    #将location.py 上傳至服務器 /tmp/test.py
    sftp.put('/tmp/id_rsa', '/tmp/a.txt')
    #将remove_path 下載到本地 local_path
    sftp.get('remove_path', 'local_path')
    
    transport.close()

關鍵字

上一篇: python md5

下一篇: Python中的dict