Python ftplib.FTP.retrlines()徹底解説:FTPファイルを行単位で取得

2025-06-06

このメソッドは、FTPサーバーからテキストファイルの内容を行ごとにダウンロードし、通常はそれをコンソールに出力したり、特定の処理を行うために使用されます。

構文

FTP.retrlines(command, callback=None)

引数

  • callback (オプション): 各行が受信されるたびに呼び出される関数です。このコールバック関数は、ダウンロードされた各行(改行文字は含まれません)を引数として受け取ります。callbackが指定されない場合、retrlines()はデフォルトで受信した行を標準出力(sys.stdout)にプリントします。
  • command (必須): 実行するFTPコマンドの文字列です。通常は、ファイルをダウンロードするための'RETR filename'のような形式になります。例えば、'RETR myfile.txt'のように指定します。

動作

  1. retrlines()は、指定されたcommandをFTPサーバーに送信します。
  2. サーバーは、コマンドに応じたデータ(通常はファイルの行)を返送します。
  3. retrlines()は、サーバーから受信した各行を処理します。
    • callback関数が指定されている場合、受信した各行はその関数に渡されます。
    • callback関数が指定されていない場合、各行はsys.stdout.write()を使って標準出力に出力され、その後に改行が追加されます。

以下に、ftplib.FTP.retrlines()の使用例を示します。

from ftplib import FTP

try:
    # FTPサーバーに接続
    ftp = FTP('ftp.example.com') # ご自身のFTPサーバーのアドレスに置き換えてください
    ftp.login('username', 'password') # ご自身のユーザー名とパスワードに置き換えてください

    print("--- README.txt の内容を直接出力 ---")
    # README.txt の内容を直接標準出力に出力する
    ftp.retrlines('RETR README.txt')

    print("\n--- 特定の処理を行うコールバック関数を使用 ---")
    def process_line(line):
        """
        受信した各行を処理するコールバック関数
        """
        print(f"処理済み行: {line.upper()}") # 例として、行を大文字にして出力

    # README.txt の内容をコールバック関数で処理する
    ftp.retrlines('RETR README.txt', process_line)

except Exception as e:
    print(f"エラーが発生しました: {e}")
finally:
    if 'ftp' in locals() and ftp.sock: # 接続が確立されていればクローズ
        ftp.quit()
        print("\nFTP接続を閉じました。")

  • RETRコマンドは、指定されたファイルをダウンロードするために使用されます。他のFTPコマンド(例: LISTでディレクトリの内容を取得するなど)も使用できますが、retrlines()は通常、複数行のテキストデータを扱うために設計されています。
  • 'ftp.example.com', 'username', 'password' は、実際のFTPサーバーの情報に置き換えてください。


ftplib.FTP.retrlines() の一般的なエラーとトラブルシューティング

エラー: ftplib.error_perm: 550 Failed to open file. (ファイルが見つからない、アクセス権がない)

これは最も一般的なエラーの一つです。

  • トラブルシューティング

    1. ファイル名の確認
      FTP クライアント(FileZilla など)を使って、ファイル名が完全に一致するか確認してください。特に大文字・小文字の区別や拡張子に注意してください。
    2. ファイルの存在確認
      同じく FTP クライアントで、そのファイルが実際にサーバー上に存在するか確認してください。
    3. アクセス権の確認
      ログインしているユーザーがそのファイルを読み取る権限を持っているか確認してください。必要であれば、FTP サーバーの管理者に問い合わせて権限を調整してもらう必要があります。
    4. 現在のディレクトリの確認
      ftp.cwd('/path/to/directory') を使って、ファイルがあるディレクトリに移動していることを確認してから retrlines() を呼び出してください。ftp.pwd() で現在の作業ディレクトリを確認できます。
    5. ftplib.FTP.nlst() または ftplib.FTP.dir() で一覧表示
      対象のファイルが存在するかどうかをコード内で確認することもできます。
      try:
          file_list = ftp.nlst() # ファイル名のみのリスト
          # file_list = [] # または ftp.dir() で詳細な情報を取得
          if 'your_file.txt' in file_list:
              print("ファイルは存在します。")
              ftp.retrlines('RETR your_file.txt')
          else:
              print("ファイル 'your_file.txt' はサーバー上に見つかりません。")
      except ftplib.error_perm as e:
          print(f"ディレクトリのリスト取得に失敗しました: {e}")
      
    • 指定されたファイルが FTP サーバー上に存在しない。
    • ファイル名に誤りがある(大文字・小文字の区別、拡張子など)。
    • ユーザーがそのファイルにアクセスする権限を持っていない。
    • 現在作業しているディレクトリ(CWD)が間違っている。

エラー: ftplib.error_perm: 530 Not logged in. または ftplib.error_perm: 500 Invalid command. (認証エラー、不正なコマンド)

retrlines() を呼び出す前に、適切にログインできていない場合に発生します。

  • トラブルシューティング

    1. ログイン情報の確認
      ftp.login('username', 'password') のユーザー名とパスワードが正しいか再確認してください。
    2. 接続の確認
      ftp = FTP('hostname') でホスト名が正しいか、そして接続が確立できているか確認してください。ファイアウォールやネットワークの問題で接続自体ができていない可能性もあります。
    3. ログイン後のステータス確認
      try:
          ftp.login('username', 'password')
          print("ログインに成功しました。")
          ftp.retrlines('RETR your_file.txt')
      except ftplib.all_errors as e:
          print(f"ログインまたは操作中にエラーが発生しました: {e}")
      
  • 原因

    • ftp.login() が成功していない。
    • ユーザー名またはパスワードが間違っている。

エラー: socket.timeout: timed out (タイムアウト)

ネットワークの遅延やサーバーの応答がない場合に発生します。

  • トラブルシューティング

    1. タイムアウト値の調整
      FTP オブジェクトを作成する際に、より長いタイムアウトを設定できます。デフォルトは短い場合があります。
      ftp = FTP('ftp.example.com', timeout=60) # 60秒に設定
      
    2. ネットワーク接続の確認
      ご自身のインターネット接続が安定しているか確認してください。
    3. サーバーの状態確認
      FTP サーバーが正常に稼働しているか、可能であれば確認してください。
  • 原因

    • ネットワーク接続が不安定、または非常に遅い。
    • FTP サーバーが応答していない、または過負荷状態にある。
    • ダウンロードしようとしているファイルが非常に大きい。

エラー: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte (エンコーディングエラー)

ダウンロードしようとしているファイルが、デフォルトのエンコーディング(通常は UTF-8)でデコードできない場合に発生します。これは、retrlines() が内部的にテキストモードでデータを処理しようとするためです。

  • 原因

    • ダウンロードしようとしているファイルが、テキストファイルではなくバイナリファイルである。
    • テキストファイルではあるが、UTF-8 以外のエンコーディング(例: Shift-JIS, EUC-JP, Latin-1 など)で保存されている。

エラー: socket.error: [Errno 10054] An existing connection was forcibly closed by the remote host (リモートホストによる接続切断)

  • トラブルシューティング

    1. FTP サーバーのタイムアウト設定を確認
      サーバー側でセッションのアイドルタイムアウトが短く設定されている可能性があります。
    2. 接続の再試行
      エラーが発生した場合に、接続から操作までを再試行するロジックを実装することを検討してください。
    3. パッシブモードの検討
      一部のファイアウォール環境では、アクティブモードの FTP 接続がブロックされることがあります。ftp.set_pasv(True) を呼び出して、パッシブモードに切り替えることを試してみてください。
      ftp = FTP('ftp.example.com')
      ftp.set_pasv(True) # パッシブモードを有効にする
      ftp.login('username', 'password')
      ftp.retrlines('RETR your_file.txt')
      
  • 原因

    • FTP サーバーが接続を切断した(アイドルタイムアウト、サーバーの再起動、DoS 保護など)。
    • ネットワーク機器(ファイアウォールなど)がセッションを切断した。
  • ファイアウォールとポート
    クライアント側(あなたのマシン)またはサーバー側のファイアウォールが、FTP のデータポート(通常はパッシブモードで一時的な高位ポート)をブロックしていないか確認してください。
  • デバッグ出力の追加
    print() ステートメントをコードの各ステップに追加して、どこで処理が停止しているか、どのような値になっているかを確認してください。
  • FTP クライアントとの比較
    FileZilla などの GUI ベースの FTP クライアントで同じ操作を試してみてください。クライアントで成功するのに Python で失敗する場合、コードの問題である可能性が高いです。クライアントでも失敗する場合、サーバー側の問題やネットワークの問題である可能性が高いです。
  • 詳細なエラーメッセージの確認
    try...except ftplib.all_errors as e: を使用して、発生した正確なエラーメッセージを捕捉し、デバッグのヒントを得てください。


まず、基本的な接続からファイル取得までの流れを示します。

例1: ファイルの内容を標準出力に直接表示する

この例では、FTP サーバー上の README.txt というファイルをダウンロードし、その内容をPythonスクリプトが実行されているコンソールに直接出力します。これが retrlines() の最もシンプルな使い方です。

from ftplib import FTP

FTP_HOST = 'ftp.example.com'  # あなたのFTPサーバーのホスト名に置き換えてください
FTP_USER = 'your_username'    # あなたのFTPユーザー名に置き換えてください
FTP_PASS = 'your_password'    # あなたのFTPパスワードに置き換えてください
FILE_TO_RETRIEVE = 'README.txt' # 取得したいファイル名に置き換えてください

try:
    print(f"FTPサーバー {FTP_HOST} に接続中...")
    with FTP(FTP_HOST) as ftp: # with ステートメントを使うと、接続が自動的に閉じられます
        print("ログイン中...")
        ftp.login(FTP_USER, FTP_PASS)
        print("ログイン成功!")

        print(f"\n--- {FILE_TO_RETRIEVE} の内容 ---")
        # retrlines() を呼び出し、ファイルの内容を直接標準出力に表示
        # コールバック関数を指定しない場合、これがデフォルトの動作です
        ftp.retrlines(f'RETR {FILE_TO_RETRIEVE}')
        print(f"--- {FILE_TO_RETRIEVE} の内容表示終了 ---")

except Exception as e:
    print(f"エラーが発生しました: {e}")

解説

  • ftp.retrlines(f'RETR {FILE_TO_RETRIEVE}'): ここが核心です。
    • 'RETR README.txt' は、FTP サーバーに「README.txt ファイルを取得(RETRieve)せよ」というコマンドを送信します。
    • retrlines() は、このコマンドの応答としてサーバーから送られてくるテキストデータを、行ごとに読み込みます。
    • コールバック関数が指定されていないため、受信した各行は自動的に sys.stdout(標準出力、つまりコンソール)に出力されます。
  • ftp.login(FTP_USER, FTP_PASS): FTP サーバーに指定されたユーザー名とパスワードでログインします。
  • with FTP(FTP_HOST) as ftp:: FTP オブジェクトを作成し、指定されたホストに接続します。with ステートメントを使うことで、スクリプトの終了時やエラー発生時に自動的に FTP 接続が閉じられるため、クリーンアップの手間が省けます。
  • from ftplib import FTP: ftplib モジュールから FTP クラスをインポートします。

例2: コールバック関数を使って各行を処理する

retrlines() の強力な機能の一つは、ダウンロードされる各行に対してカスタムの処理を実行できるコールバック関数を指定できることです。この例では、ダウンロードした各行を大文字に変換して表示します。

from ftplib import FTP

FTP_HOST = 'ftp.example.com'
FTP_USER = 'your_username'
FTP_PASS = 'your_password'
FILE_TO_RETRIEVE = 'sample.txt' # 処理したいテキストファイル名に置き換えてください

def process_line_callback(line):
    """
    retrlines() によって呼び出されるコールバック関数。
    受信した各行(改行文字なし)を引数として受け取ります。
    """
    print(f"処理済み行 (大文字): {line.upper()}")
    # ここでデータベースに保存したり、リストに追加したり、
    # その他のテキスト処理を行うことができます。

try:
    print(f"FTPサーバー {FTP_HOST} に接続中...")
    with FTP(FTP_HOST) as ftp:
        print("ログイン中...")
        ftp.login(FTP_USER, FTP_PASS)
        print("ログイン成功!")

        print(f"\n--- {FILE_TO_RETRIEVE} の内容をコールバックで処理 ---")
        # retrlines() にコールバック関数を渡す
        ftp.retrlines(f'RETR {FILE_TO_RETRIEVE}', process_line_callback)
        print(f"--- {FILE_TO_RETRIEVE} の処理終了 ---")

except Exception as e:
    print(f"エラーが発生しました: {e}")

解説

  • ftp.retrlines(f'RETR {FILE_TO_RETRIEVE}', process_line_callback): retrlines() の2番目の引数として、定義したコールバック関数を渡しています。これにより、デフォルトの標準出力への表示ではなく、この関数が各行の処理を担当します。
  • print(f"処理済み行 (大文字): {line.upper()}"): この例では、受け取った行を大文字に変換して出力しています。実際のアプリケーションでは、行をパースしたり、特定の情報を抽出したり、別のファイルに書き込んだりするなどの処理を行うことができます。
  • def process_line_callback(line):: これがカスタムのコールバック関数です。retrlines() がサーバーから1行を受信するたびに、この関数が呼び出され、受信した行(改行文字は含まれない)が line 引数として渡されます。

例3: ファイルの内容をリストに格納する

ファイルの内容をメモリ上のリストにすべて読み込みたい場合、コールバック関数を使って各行をリストに追加することができます。

from ftplib import FTP

FTP_HOST = 'ftp.example.com'
FTP_USER = 'your_username'
FTP_PASS = 'your_password'
FILE_TO_RETRIEVE = 'data.log' # リストに格納したいファイル名に置き換えてください

retrieved_lines = [] # ダウンロードした行を格納するリスト

def store_line_callback(line):
    """
    受信した行をグローバルリストに格納するコールバック関数。
    """
    retrieved_lines.append(line)

try:
    print(f"FTPサーバー {FTP_HOST} に接続中...")
    with FTP(FTP_HOST) as ftp:
        print("ログイン中...")
        ftp.login(FTP_USER, FTP_PASS)
        print("ログイン成功!")

        print(f"\n--- {FILE_TO_RETRIEVE} の内容をリストに格納 ---")
        ftp.retrlines(f'RETR {FILE_TO_RETRIEVE}', store_line_callback)
        print(f"--- {FILE_TO_RETRIEVE} の格納終了 ---")

        print(f"\n格納された行数: {len(retrieved_lines)} 行")
        print("最初の5行:")
        for i, line in enumerate(retrieved_lines[:5]):
            print(f"  {i+1}: {line}")

except Exception as e:
    print(f"エラーが発生しました: {e}")

解説

  • 処理が完了した後、retrieved_lines リストには data.log ファイルの全行が格納されており、それらを使って後続の処理を行うことができます。
  • def store_line_callback(line):: このコールバック関数は、line 引数として受け取った各行を retrieved_lines リストに追加します。
  • retrieved_lines = []: ダウンロードされた行を一時的に保持するための空のリストを初期化します。
  • 大規模なファイル
    retrlines() で非常に大きなファイルをダウンロードし、すべての行をメモリ上のリストに格納する場合(例3)、メモリを大量に消費する可能性があります。その場合は、コールバック関数内で直接ファイルを書き出すなど、メモリ効率の良い方法を検討してください。
  • バイナリファイル
    retrlines() はテキストファイル(行単位でデコードできるファイル)にのみ適しています。画像や圧縮ファイルのようなバイナリファイルをダウンロードする場合は、ftplib.FTP.retrbinary() を使用する必要があります。
  • エラーハンドリング
    上記の例では基本的な try...except ブロックを使用していますが、実際のアプリケーションでは ftplib.error_permsocket.timeout など、より具体的な例外を捕捉し、それぞれのエラーに対して適切な処理を行うことが重要です。


  1. バイナリファイルをダウンロードする場合
    retrlines() はテキストモードでデータを処理するため、画像、圧縮ファイル、実行ファイルなどのバイナリファイルには適していません。
  2. ファイル全体を一度に(またはチャンクで)保存する場合
    行単位の処理が必要なく、ファイルをローカルに保存したい場合。
  3. 特定のエンコーディングでファイルを読み込みたい場合
    retrlines() はデフォルトのシステムエンコーディングまたは ftp.encoding に依存するため、異なるエンコーディングのファイルを確実に扱うのが難しい場合があります。

以下に、主な代替メソッドとそれらの使用例を挙げます。

ftplib.FTP.retrbinary() (バイナリファイルのダウンロード)

これは retrlines() の最も直接的な代替であり、バイナリファイルをダウンロードする際に使用されます。ファイルの内容をチャンク(塊)で読み込み、指定されたコールバック関数にそのチャンクを渡します。通常は、チャンクをローカルファイルに書き込むために使用します。

特徴

  • コールバック関数で、進捗表示などのカスタム処理も可能。
  • チャンクサイズを指定して、効率的にメモリを使用できる。
  • バイナリデータのダウンロードに最適。

構文

FTP.retrbinary(command, callback, blocksize=8192, rest=None)
  • rest: 途中からダウンロードを再開する場合のオフセット(バイト単位)。
  • blocksize: 一度に受信するバイト数(チャンクサイズ)。デフォルトは 8192 バイト。
  • callback: 各チャンクが受信されるたびに呼び出される関数。受信したバイト列を引数として受け取る。
  • command: 'RETR filename' の形式の FTP コマンド。


バイナリファイル(例: image.jpg)をダウンロードしてローカルに保存する

from ftplib import FTP
import os

FTP_HOST = 'ftp.example.com'
FTP_USER = 'your_username'
FTP_PASS = 'your_password'
REMOTE_FILE = 'image.jpg' # ダウンロードしたいバイナリファイル名
LOCAL_FILE = 'downloaded_image.jpg' # ローカル保存ファイル名

def handle_binary_data(chunk):
    """
    受信したバイナリデータをファイルに書き込むコールバック関数
    """
    local_file_handle.write(chunk)

try:
    print(f"FTPサーバー {FTP_HOST} に接続中...")
    with FTP(FTP_HOST) as ftp:
        print("ログイン中...")
        ftp.login(FTP_USER, FTP_PASS)
        print("ログイン成功!")

        print(f"\n--- {REMOTE_FILE} をバイナリモードでダウンロード ---")
        with open(LOCAL_FILE, 'wb') as local_file_handle: # 'wb' でバイナリ書き込みモード
            ftp.retrbinary(f'RETR {REMOTE_FILE}', handle_binary_data)
        print(f"--- {REMOTE_FILE}{LOCAL_FILE} にダウンロード完了 ---")

        # ファイルサイズの確認(オプション)
        if os.path.exists(LOCAL_FILE):
            print(f"ダウンロードされたファイルサイズ: {os.path.getsize(LOCAL_FILE)} バイト")

except Exception as e:
    print(f"エラーが発生しました: {e}")

ftplib.FTP.storlines() と ftplib.FTP.storbinary() (ファイルのアップロード)

これはダウンロードの代替というよりは、アップロードの代替ですが、retrlines() と対になる概念です。retrlines() がサーバーから行を受信するのに対し、storlines() はローカルから行をサーバーに送信します。

  • ftplib.FTP.storbinary(command, file, blocksize=8192, callback=None, rest=None): バイナリファイルをサーバーにアップロードします。file オブジェクト(open('image.jpg', 'rb') で開いたものなど)を引数として受け取り、その内容をチャンクでサーバーに送信します。
  • ftplib.FTP.storlines(command, file): テキストファイルをサーバーにアップロードします。file オブジェクト(open('file.txt', 'r') で開いたものなど)を引数として受け取り、その内容を行単位でサーバーに送信します。

これらのメソッドは、retrlines() で取得したデータを加工して再びサーバーにアップロードするようなシナリオで役立ちます。

io.BytesIO や io.StringIO と組み合わせてメモリ上で処理する

ファイルを直接ディスクに保存せず、メモリ上で処理したい場合に便利です。

  • io.StringIO: テキストデータ用。retrlines() と組み合わせて使用することも可能ですが、retrlines() 自体が内部でデコードを行うため、直接テキストを処理したい場合に便利です。
  • io.BytesIO: バイナリデータ用。retrbinary() と組み合わせて使用。


テキストファイルをダウンロードしてメモリ上の文字列として取得し、後で処理する (これは retrlines() のコールバック関数を工夫する例に近いですが、明示的に StringIO を使うことで、よりPythonのファイルオブジェクトに近い感覚で扱えます)。

from ftplib import FTP
import io # ioモジュールをインポート

FTP_HOST = 'ftp.example.com'
FTP_USER = 'your_username'
FTP_PASS = 'your_password'
REMOTE_FILE = 'report.txt'

try:
    print(f"FTPサーバー {FTP_HOST} に接続中...")
    with FTP(FTP_HOST) as ftp:
        print("ログイン中...")
        ftp.login(FTP_USER, FTP_PASS)
        print("ログイン成功!")

        print(f"\n--- {REMOTE_FILE} をメモリにダウンロード ---")
        # StringIO オブジェクトを作成し、コールバック関数でそこに書き込む
        string_buffer = io.StringIO()
        ftp.retrlines(f'RETR {REMOTE_FILE}', lambda line: string_buffer.write(line + '\n'))
        # retrlines は改行を含まない行を渡すため、手動で改行を追加

        downloaded_content = string_buffer.getvalue()
        print(f"--- {REMOTE_FILE} のダウンロード完了 ---")

        print("\nダウンロードされた内容の最初の100文字:")
        print(downloaded_content[:100])

        # ここで downloaded_content を好きなように処理できます
        line_count = downloaded_content.count('\n')
        print(f"ダウンロードされた行数 (概算): {line_count} 行")

except Exception as e:
    print(f"エラーが発生しました: {e}")

解説

  • downloaded_content = string_buffer.getvalue(): ダウンロードが完了した後、string_buffer に格納されているすべての文字列を取得します。
  • lambda line: string_buffer.write(line + '\n'): 無名関数(ラムダ関数)をコールバックとして渡し、受信した各行を string_buffer に書き込みます。retrlines() は改行文字を含まない行を渡すため、手動で '\n' を追加する必要があります。
  • string_buffer = io.StringIO(): メモリ内で文字列を読み書きするための StringIO オブジェクトを作成します。これは、あたかもファイルのように振る舞います。
  • import io: io モジュールをインポートします。

ftplib は標準ライブラリであり、FTP プロトコルの低レベルな部分を直接扱います。しかし、より高レベルな抽象化や、SFTP(SSH File Transfer Protocol)のような異なるプロトコルを扱いたい場合は、paramikopysftp といったサードパーティライブラリが非常に強力な代替手段となります。

特徴

  • ファイル操作がより簡潔に記述できる。
  • より直感的で高レベルな API を提供することが多い。
  • SFTP をサポートするため、セキュアなファイル転送が可能(FTP は通常暗号化されない)。


paramiko を使って SFTP でファイルをダウンロードする(インストールが必要です: pip install paramiko

import paramiko
import os

SFTP_HOST = 'your_sftp_host' # SFTPサーバーのホスト名
SFTP_PORT = 22 # 通常SFTPはポート22
SFTP_USER = 'your_sftp_username'
SFTP_PASS = 'your_sftp_password'
REMOTE_FILE = '/path/to/remote/file.txt'
LOCAL_FILE = 'downloaded_sftp_file.txt'

try:
    print(f"SFTPサーバー {SFTP_HOST}:{SFTP_PORT} に接続中...")
    transport = paramiko.Transport((SFTP_HOST, SFTP_PORT))
    transport.connect(username=SFTP_USER, password=SFTP_PASS)
    sftp = paramiko.SFTPClient.from_transport(transport)
    print("SFTP接続成功!")

    print(f"\n--- {REMOTE_FILE} を SFTP でダウンロード ---")
    sftp.get(REMOTE_FILE, LOCAL_FILE)
    print(f"--- {REMOTE_FILE}{LOCAL_FILE} にダウンロード完了 ---")

    if os.path.exists(LOCAL_FILE):
        print(f"ダウンロードされたファイルサイズ: {os.path.getsize(LOCAL_FILE)} バイト")

except paramiko.AuthenticationException:
    print("SFTP認証に失敗しました。ユーザー名またはパスワードを確認してください。")
except paramiko.SSHException as e:
    print(f"SFTP接続エラー: {e}")
except Exception as e:
    print(f"その他のエラーが発生しました: {e}")
finally:
    if 'sftp' in locals() and sftp:
        sftp.close()
    if 'transport' in locals() and transport:
        transport.close()

  • SFTP は FTP とは異なるプロトコルであり、通常は認証情報が異なり、ポートも異なります。
  • sftp.get(REMOTE_FILE, LOCAL_FILE): リモートファイルをローカルパスに直接ダウンロードします。非常にシンプルです。
  • paramiko.SFTPClient.from_transport(transport): 確立された SSH 接続から SFTP クライアントを作成します。
  • paramiko.Transport: SSH 接続を確立します。
代替方法主な用途ftplib.FTP.retrlines() との違い
ftplib.FTP.retrbinary()バイナリファイル(画像、zipなど)のダウンロードデータを行ではなくバイトのチャンクで扱う
ftplib.FTP.storlines() / storbinary()ファイルのアップロードダウンロードではなくサーバーへの送信
io.StringIO / io.BytesIO + コールバックファイルをディスクに保存せずメモリ上で処理データ処理の場所(メモリ vs. ディスク)
paramiko (SFTP)セキュアなファイル転送、高レベルな操作FTP ではなく SFTP プロトコルを使用、より使いやすい API