6

更新 #1

問題のコードは、安定した接続(ローカル ネットワークやイントラネットなど)に適しています。

更新 #2

FTPClient次のことができる ftplib を使用してクラスを実装しました。

  1. ダウンロードの進行状況を監視する
  2. タイムアウトまたは切断の場合に再接続する
  3. ファイルのダウンロードを数回試行します
  4. 現在のダウンロード速度を表示します。

再接続後、切断ポイントからダウンロード プロセスを続行します (FTP サーバーがサポートしている場合)。詳細については、以下の私の回答を参照してください。


質問

FTP経由で大量の大きなファイル(ファイルあたり0.3〜1.5Gb * 200〜300ファイル)を毎日ダウンロードし、ファイルを処理するタスクをpythonに実装する必要があります。私はftplib経由でそれをしました。しかし、時々ハングアップし、一部のファイルのダウンロードを完了できません。問題を解決するために KEEPALIVE 設定でプレイを開始しましたが、まだ良い結果が得られません。

with closing(ftplib.FTP()) as ftp:
    try:
        ftp.connect(self.host, self.port, 30*60) #30 mins timeout
        # print ftp.getwelcome()
        ftp.login(self.login, self.passwd)
        ftp.set_pasv(True)
        ftp.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
        ftp.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 75)
        ftp.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60)
        with open(local_filename, 'w+b') as f:
            res = ftp.retrbinary('RETR %s' % orig_filename, f.write)

            if not res.startswith('226 Transfer complete'):
                logging.error('Downloaded of file {0} is not compile.'.format(orig_filename))
                os.remove(local_filename)
                return None

        os.rename(local_filename, self.storage + filename + file_ext)
        ftp.rename(orig_filename, orig_filename + '.copied')

        return filename + file_ext

    except:
            logging.exception('Error during download from FTP')

詳細

  • 通常、ファイルのダウンロードには 7 ~ 15 分かかります。
  • FTP サーバーは、ファイルが完全にダウンロードされていることを常にログに示していますが、クライアント部分はハングしています。毎回ではありませんが、時々です。

質問

  • 切断のせいでしょうか?
  • ダウンロードプロセスのモニターを実装し、切断された場合に再接続する方法
4

1 に答える 1

12

良い提案やコード サンプルが見つからなかったため、独自のソリューションを実装しました。コードで使用したいくつかのアイデアについて、Stackoverflow コミュニティに感謝します。コードのサイズ(〜120行)のため、コードをGitHub(pyFTPclient )に配置しました。

質の悪いネットワーク (3G モバイル インターネットを含む) でソリューションをテストしたところ、問題なく動作しました。しかし、もちろんいくつかのバグがあるかもしれません。

コメントや提案をいただければ幸いです。前もって感謝します。

于 2013-10-18T19:11:23.017 に答える