2017-08-12 78 views
1

我想創建一個代碼來使用pysftp和多處理庫下載相同類型的N個文件。我做了一個基本的python培訓,得到了一些代碼並將它們合併爲一個,但我無法解決它。如果有人幫助我,我會很感激。該錯誤發生在vFtp.close()命令之後。假設開始同時下載的部分。並行下載與多處理和PySftp

from multiprocessing import Pool 
import pysftp 
import os 

vHost='10.11.12.13' 
vLogin='admin' 
vPwd='pass1234' 
vFtpPath='/export/home/' 

os.chdir('d:/test/') 
os.getcwd() 

cnopts=pysftp.CnOpts() 
cnopts.hostkeys = None 

vFtp=pysftp.Connection(vHost,username=vLogin,password=vPwd,cnopts=cnopts) 
vFtp.cwd(vFtpPath) 
vObjectList=vFtp.listdir() 
vFileList=[] 
vFoldList=[] 

for vObject in vObjectList: 
    vType=str(vFtp.lstat(vObject))[:1] 
    if vType!='d': 
     vFileList.append(vObject) 
    else: 
     vFoldList.append(vObject) 

vFtp.close() 

def fDownload(vFileAux): 
    vFtpAux=pysftp.Connection(vHost,username=vLogin,password=vPwd,cnopts=cnopts) 
    vFtpAux.cwd(vFtpPath) 
    vFtpAux.get(vFileAux,preserve_mtime=True) 
    vFtpAux.close() 

if __name__ == "__main__": 
    vPool=Pool(3) 
    vPool.map(fDownload,vFileList) 

回答

1

它看起來像你試圖獲得文件列表,然後使用多個進程同時下載它們。

不用手動檢查文件,請嘗試使用walktree方法連接對象上:pysftp walktree

下面是我在Python 3.5製備的工作例子。我只是使用本地ftp服務器和小文件,所以我模擬了一個下載延遲。更改max_workers參數以設置同時下載的數量。

"""Demo using sftp to download files simultaneously.""" 
import pysftp 
import os 
from concurrent.futures import ProcessPoolExecutor 
import time 


def do_nothing(s): 
    """ 
    Using this as the callback for directories and unknown items found 
    using walktree. 
    """ 
    pass 


def download(file): 
    """ 
    Simulates a 1-second download. 
    """ 
    with pysftp.Connection(
      host='convox', username='abc', private_key='/home/abc/test') as sftp: 

     time.sleep(1) 
     print('Downloading {}'.format(file)) 
     sftp.get(file) 


def get_list_of_files(remote_dir): 
    """ 
    Walks remote directory tree and returns list of files. 
    """ 
    with pysftp.Connection(
      host='convox', username='abc', private_key='/home/abc/test') as sftp: 

     files = [] 

     # if this finds a file it will send the filename to the file callback 
     # which in this case just appends to the 'files' list 
     sftp.walktree(remote_dir, fcallback=files.append, 
         dcallback=do_nothing, ucallback=do_nothing) 

    return files 

if __name__ == '__main__': 
    remote_dir = '/home/abc/remoteftp/' 
    download_target = '/home/abc/localftp/' 

    # if you don't specify a localpath in sftp.get then it just downloads to 
    # the os cwd, so set it here 
    os.chdir(download_target) 

    files = get_list_of_files(remote_dir) 
    pool = ProcessPoolExecutor(max_workers=4) 
    pool.map(download, files) 

編輯:ProcessPoolExecutor是運行在多個CPU內核的東西,會被你的處理器的限制。對於下載等網絡任務,您可以使用線程代替。在上面的代碼中,這只是一個更改:而不是ProcessPoolExecutor導入並使用ThreadPoolExecutor。那麼你可以使用更多的max_workers

+0

非常感謝,非常簡單明瞭的例子。我會做一些測試並讓你知道結果。 –