2013-02-24 55 views
3

的確切人數所以,我已經能夠使用多上傳多個文件一次給定服務器具有以下兩個功能:多重FTP上傳隨着連接

import ftplib,multiprocessing,subprocess 

def upload(t): 
    server=locker.server,user=locker.user,password=locker.password,service=locker.service #These all just return strings representing the various fields I will need. 
    ftp=ftplib.FTP(server) 
    ftp.login(user=user,passwd=password,acct="") 
    ftp.storbinary("STOR "+t.split('/')[-1], open(t,"rb")) 
    ftp.close() # Doesn't seem to be necessary, same thing happens whether I close this or not 

def ftp_upload(t=files,server=locker.server,user=locker.user,password=locker.password,service=locker.service): 
    parsed_targets=parse_it(t) 
    ftp=ftplib.FTP(server) 
    ftp.login(user=user,passwd=password,acct="") 
    remote_files=ftp.nlst(".") 
    ftp.close() 
    files_already_on_server=[f for f in t if f.split("/")[-1] in remote_files] 
    files_to_upload=[f for f in t if not f in files_already_on_server] 
    connections_to_make=3 #The maximum connections allowed the the server is 5, and this error will pop up even if I use 1 
    pool=multiprocessing.Pool(processes=connections_to_make) 
    pool.map(upload,files_to_upload) 

我的問題是我(非常有規律)最終得到的錯誤,如:

File "/usr/lib/python2.7/multiprocessing/pool.py", line 227, in map 
    return self.map_async(func, iterable, chunksize).get() 
    File "/usr/lib/python2.7/multiprocessing/pool.py", line 528, in get 
    raise self._value 
ftplib.error_temp: 421 Too many connections (5) from this IP 

注:還有,偶爾出現超時錯誤,但我再次等待它後的醜陋的頭,在這一點上,我會發布它。

當我使用命令行(即「ftp -inv」,「open SERVER」,「user USER PASSWORD」,「mput * .rar」)時,即使我有(for例如)一次運行3個實例。

我已經通讀了ftplib和multiprocessing文檔,我無法弄清楚它是什麼導致了這些錯誤。這是一個問題,因爲我經常備份大量數據和大量文件。

  1. 有沒有什麼辦法可以避免這些錯誤,或者有一種不同的方法讓/腳本執行此操作嗎?
  2. 有沒有辦法告訴腳本,如果它有這個錯誤,它應該等待一秒鐘,然後恢復它的工作?
  3. 有沒有一種方法可以讓腳本按照它們在列表中的順序上傳文件(當然,速度差異意味着它們並不總是4個連續的文件,但目前看起來基本上是隨機)?
  4. 有人可以解釋爲什麼/如何有更多的連接正在同步到這臺服務器比腳本要求?

所以,只是處理異常似乎正在工作(除偶爾的遞歸錯誤...仍然沒有他媽的想法到底是怎麼回事)。

根據#3,我並沒有在尋找100%的順序,只是腳本會選擇列表中的下一個文件進行上傳(因此處理速度的差異會導致訂單不是完全順序的,會比現在的系統少變化,這似乎幾乎是無序的)。

+0

也許庫會自動獲得更好的性能產生併發連接。 [l發表了一般性的關於這個問題的詳細答案,這可能會有所幫助](https://stackoverflow.com/questions/30797269/warning-ftp-login-i-cant-accept-more-than-6-connections-作爲最同一用戶費/ 45131091#45131091) – 2017-07-16 17:19:33

回答

1

明確回答(2)有沒有辦法告訴腳本,如果它有這個錯誤,它應該等待一秒鐘,然後恢復它的工作?

是的。

ftplib.error_temp: 421 Too many connections (5) from this IP 

這是一個例外。你可以抓住它並處理它。而Python不支持尾調用,所以這是很可怕的形式,也可以是這樣簡單:

def upload(t): 
    server=locker.server,user=locker.user,password=locker.password,service=locker.service #These all just return strings representing the various fields I will need. 
    try: 
     ftp=ftplib.FTP(server) 
     ftp.login(user=user,passwd=password,acct="") 
     ftp.storbinary("STOR "+t.split('/')[-1], open(t,"rb")) 
     ftp.close() # Doesn't seem to be necessary, same thing happens whether I close this or not 
    except ftplib.error_temp: 
     ftp.close() 
     sleep(2) 
     upload(t) 

至於你的問題(3)如果這是你想要的,做上傳順序,不在平行下。

我期待着您發佈更新並回答(4)。我想到的唯一一件事就是通過ftp連接到這個IP的其他進程。

3

你可以嘗試每個進程使用一個ftp實例:

def init(*credentials): 
    global ftp 
    server, user, password, acct = credentials 
    ftp = ftplib.FTP(server) 
    ftp.login(user=user, passwd=password, acct=acct) 

def upload(path): 
    with open(path, 'rb') as file: 
     try: 
      ftp.storbinary("STOR " + os.path.basename(path), file) 
     except ftplib.error_temp as error: # handle temporary error 
      return path, error 
     else: 
      return path, None 

def main(): 
    # ... 
    pool = multiprocessing.Pool(processes=connections_to_make, 
           initializer=init, initargs=credentials) 
    for path, error in pool.imap_unordered(upload, files_to_upload): 
     if error is not None: 
      print("failed to upload %s" % (path,))