3

そのため、マルチプロセッシングを使用して、次の 2 つの関数を使用して特定のサーバーに複数のファイルを一度にアップロードすることができました。

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 USERNAME PASSWORD"、"mput *.rar") を使用すると、(たとえば) 3 つのインスタンスがある場合でも、このエラーは発生しません。この実行中のすぐに。

ftplib と multiprocessing のドキュメントを読みましたが、これらのエラーの原因がわかりません。私は定期的に大量のデータと多数のファイルをバックアップしているので、これはやや問題です。

  1. これらのエラーを回避する方法はありますか、またはスクリプトにこれを実行させる別の方法はありますか?
  2. スクリプトにこのエラーが発生した場合、1 秒待ってから作業を再開するように指示する方法はありますか?
  3. スクリプトがリストにあるのと同じ順序でファイルをアップロードする方法はありますか (もちろん、速度の違いは、すべてが常に 4 つの連続したファイルになるとは限らないことを意味しますが、現時点では順序は基本的にランダムに見えます)。
  4. 誰かが、スクリプトが要求しているよりも多くの接続がこのサーバーに対して同時に行われている理由/方法を説明できますか?

したがって、例外を処理するだけで機能しているように見えます(時折の再帰エラーを除いて...まだ何が起こっているのかわかりません)。

#3に従って、私はそれが100%順番になることを望んでいませんでした.スクリプトがアップロードするリストの次のファイルを選択するだけでした(したがって、プロセス速度の違いにより、順番が完全ではない可能性があります.シーケンシャルであれば、ほとんど順序付けされていないように見える現在のシステムよりも変動性が少なくなります)。

4

2 に答える 2

4

ftpプロセスごとに 1 つのインスタンスを使用してみることができます。

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,))
于 2013-02-24T17:01:15.990 に答える
1

具体的に答える (2) スクリプトにこのエラーが発生した場合、1 秒待ってから作業を再開するように指示する方法はありますか?

はい。

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) に対する回答を更新して投稿することを楽しみにしています。私の頭に浮かぶ唯一のことは、このIPへのftp接続を持つ他のプロセスです。

于 2013-02-24T16:18:21.570 に答える