ftplib.FTP.storlines()
ftplib.FTP.storlines()
は、Pythonの ftplib
モジュールが提供する FTP
クラスのメソッドの一つで、FTPサーバーにファイルをアップロードするために使用されます。特に、このメソッドはテキストファイルをアップロードするのに適しています。
以下に詳しく説明します。
storlines()
メソッドは、指定されたファイルオブジェクトからデータを読み込み、FTPサーバーに「行モード」で送信します。FTPにおける行モード(またはASCIIモード)転送では、改行コード(CR/LF)が自動的に変換されるため、異なるOS間でのテキストファイルの互換性を保つことができます。
バイナリファイル(画像、動画、実行ファイルなど)をアップロードする場合は、storlines()
ではなく storbinary()
メソッドを使用する必要があります。storbinary()
はバイナリモードで転送を行うため、改行コードの変換は行われません。
storlines()
メソッドのシグネチャ
storlines(cmd, fp, callback=None)
callback
(オプション): 各行が送信された後に呼び出される関数です。コールバック関数は1つの引数(送信された行データ)を受け取ります。進捗表示などに利用できます。fp
: アップロードするファイルの内容が格納されているファイルオブジェクトです。このファイルオブジェクトは、readline()
メソッドでデータを読み取れるように開かれている必要があります。通常は'r'
または'rb'
モードで開かれます(最近のPythonでは'rb'
が推奨されるケースもあります)。cmd
: FTPサーバーに送信するコマンド文字列です。通常はSTOR filename
の形式で指定します。filename
はサーバー上の保存先ファイル名です。
使用例
テキストファイルをFTPサーバーにアップロードする基本的な例を以下に示します。
from ftplib import FTP
# FTPサーバーへの接続情報
FTP_HOST = "your_ftp_host"
FTP_USER = "your_username"
FTP_PASS = "your_password"
LOCAL_FILE_PATH = "local_text_file.txt" # ローカルのアップロードしたいテキストファイル
REMOTE_FILE_NAME = "remote_text_file.txt" # サーバーに保存するファイル名
try:
# FTPオブジェクトを作成し、接続
ftp = FTP(FTP_HOST)
print(ftp.getwelcome()) # サーバーからのウェルカムメッセージを表示
# ログイン
ftp.login(user=FTP_USER, passwd=FTP_PASS)
print("ログインに成功しました。")
# アップロードするファイルを読み取りモードで開く
# テキストファイルの場合でも、環境によっては 'rb' (バイナリ読み込み) を推奨するケースがあります。
# ただし、storlines()は内部で readline() を使うため、テキストデータとして扱われます。
with open(LOCAL_FILE_PATH, 'rb') as fp: # 'rb'で開くのがより安全で一般的です
# ファイルをアップロード
# "STOR" コマンドに続けて、サーバー上でのファイル名を指定
response = ftp.storlines(f"STOR {REMOTE_FILE_NAME}", fp)
print(f"アップロード応答: {response}")
print(f"{LOCAL_FILE_PATH} を {REMOTE_FILE_NAME} としてFTPサーバーにアップロードしました。")
except Exception as e:
print(f"エラーが発生しました: {e}")
finally:
if 'ftp' in locals() and ftp:
ftp.quit() # 接続を閉じる
print("FTP接続を閉じました。")
- エラーハンドリング:
FTP通信はネットワークの状態やサーバーの設定に依存するため、エラーハンドリング(
try-except-finally
ブロック)を適切に行い、接続のクローズを忘れないようにすることが重要です。 - バイナリファイル:
繰り返しになりますが、画像や実行ファイルなどのバイナリファイルをアップロードする場合は、
storlines()
ではなくstorbinary()
を使用してください。バイナリファイルをstorlines()
でアップロードすると、データが破損する可能性があります。 - ファイルモード:
storlines()
は内部でファイルオブジェクトのreadline()
メソッドを使用するため、ファイルはテキストデータとして扱われます。ただし、Python 3ではファイルをバイナリモード('rb'
)で開くことが推奨されるケースがあります。これは、改行コードの自動変換をftplib
に任せるためです。'r'
で開くと、Pythonのテキストモードがすでに改行変換を行うため、二重変換による問題が発生する可能性があります。
TypeError: a bytes-like object is required, not 'str'
原因
このエラーは、storlines()
メソッドに渡すファイルオブジェクトがテキストモード(例: open('file.txt', 'r')
)で開かれている場合に発生します。ftplib
は内部でバイトデータを期待しているため、文字列を直接渡すとこのエラーが出ます。
トラブルシューティング
ファイルをバイナリモードで開いてください。'rb'
(read binary) モードでファイルを開くのが正しい方法です。storlines()
はテキストファイルを想定していますが、Python 3ではファイルの内容をバイトとして読み込み、ftplib
内部で適切な改行コード変換が行われます。
# 悪い例 (TypeErrorが発生する可能性あり)
# with open('local_text_file.txt', 'r') as fp:
# ftp.storlines(f"STOR {REMOTE_FILE_NAME}", fp)
# 良い例
with open('local_text_file.txt', 'rb') as fp: # 'rb' で開く
ftp.storlines(f"STOR {REMOTE_FILE_NAME}", fp)
ファイルの内容が壊れる(文字化け、改行コードの問題)
原因
storlines()
はテキストファイル用ですが、WindowsとLinux/macOSでは改行コードの扱いが異なります(CRLF vs LF)。ftplib
はASCIIモード転送を行うため、通常は自動的に改行コードを変換しますが、ファイルを開く際のエンコーディング指定や、storlines()
以外の方法(例: storbinary()
をテキストファイルに使用)を用いると問題が発生することがあります。
トラブルシューティング
- バイナリファイルの場合
テキストファイルではない(画像、ZIPなど)場合は、storlines()
ではなく、必ずstorbinary()
を使用してください。storbinary()
はバイトデータをそのまま転送し、改行コード変換を行いません。 - エンコーディングの確認
ローカルファイルのエンコーディング(UTF-8, Shift_JISなど)がFTPサーバーの期待するエンコーディングと異なる場合、文字化けが発生する可能性があります。ftplib
はファイルの内容のエンコーディングを自動的に判断しないため、サーバー側で解釈できない場合は文字化けの原因になります。もしサーバー側で特定のエンコーディングが要求される場合は、ファイル作成時にそのエンコーディングで保存し、'rb'
で読み込むのが安全です。 - storlines() を使う場合
上記の通り、ファイルを'rb'
(read binary) モードで開くことを徹底してください。これにより、Pythonがファイルのバイトデータをそのままftplib
に渡し、ftplib
がFTPプロトコルに従って改行コードを適切に処理します。
ftplib.error_perm: 550 Permission denied など、FTPサーバーからのパーミッションエラー
原因
- 指定されたディレクトリが存在しない。
- 指定されたファイル名がサーバー側で既に存在し、上書きが許可されていない(または上書きできない状況にある)。
- 指定されたリモートパスにファイルを書き込む権限がない。
トラブルシューティング
- ファイル名
サーバーに既に同名のファイルがある場合、上書きされるか、エラーになるかはFTPサーバーの設定によります。必要に応じて、一意のファイル名を生成したり、既存ファイルを削除してからアップロードすることを検討してください。 - ディレクトリの存在確認と作成
アップロード先のディレクトリがサーバー上に存在するか確認し、存在しない場合はftp.mkd('directory_name')
で作成するか、ftp.cwd('directory_name')
で既存のディレクトリに移動してからアップロードしてください。 - 権限の確認
FTPサーバーにログインしているユーザーに、対象ディレクトリへの書き込み権限があるか確認してください。FTPクライアント(FileZillaなど)で手動でアップロードを試みて、権限の問題かを確認するのが有効です。
接続関連のエラー (ConnectionRefusedError, ftplib.error_temp, ftplib.error_perm, socket.timeout)
原因
- アクティブモード/パッシブモードの問題。
- タイムアウトが発生した(ネットワーク遅延、サーバーの応答が遅いなど)。
- FTPサーバーがダウンしている、または一時的に利用できない。
- ファイアウォールによって接続がブロックされている(ローカルまたはサーバー側)。
- FTPサーバーに接続できない(IPアドレスやポートが間違っている)。
トラブルシューティング
- パッシブモード/アクティブモード
FTPにはデータ転送のための2つのモードがあります。- パッシブモード (Passive Mode - PASV)
クライアントがサーバーにデータ接続用のポートを要求し、クライアントからサーバーへ接続します。これが今日のほとんどのファイアウォール環境で推奨されるモードです。ftplib
はデフォルトでパッシブモードを使用します。 - アクティブモード (Active Mode - PORT)
サーバーがクライアントにデータ接続しに戻ってきます。クライアント側にファイアウォールがある場合、この接続がブロックされる可能性が高いです。 もしパッシブモードで問題が発生する場合、明示的にアクティブモードに切り替えることもできますが、これは通常ファイアウォールの問題を伴います。
ただし、多くの場合、アクティブモードへの切り替えは新たなファイアウォール問題を引き起こすため、まずはパッシブモードでの設定(サーバー側でのポート開放など)を検討すべきです。ftp.set_pasv(False) # アクティブモードに設定
- パッシブモード (Passive Mode - PASV)
- タイムアウト設定
ftplib.FTP()
コンストラクタやconnect()
メソッドにtimeout
パラメータを渡して、タイムアウト値を調整してみてください。ftp = FTP(FTP_HOST, timeout=60) # 60秒のタイムアウト
- FTPサーバーの状態確認
FTPサーバーが正常に稼働しているか確認してください。 - ファイアウォールの確認
ローカルPCやネットワークのファイアウォール、またはFTPサーバー側のファイアウォールがFTP接続(特にデータ転送ポート)をブロックしていないか確認してください。 - ホスト名/IPアドレスとポートの確認
接続情報が正しいか再確認してください。デフォルトのFTPポートは21です。
ftplib.error_proto や ftplib.error_reply
原因
これらはFTPサーバーから予期しない応答や、プロトコル仕様に合致しない応答が返された場合に発生します。サーバー側の設定ミスや、非標準のFTPサーバーである可能性、または通信の途中で問題が発生した場合に起こりえます。
- FTPサーバーの互換性
特定のFTPサーバーが標準から逸脱した動作をする場合、ftplib
がうまく対応できないことがあります。その場合は、別のFTPライブラリの検討や、サーバー管理者に問い合わせる必要があるかもしれません。 - サーバーのログ確認
サーバー側のFTPログを確認することで、何が起こったのか、サーバーがどのようなエラーを返したのかを特定できる場合があります。
- 簡単なファイルのアップロードでテスト
まずは非常に小さな、単純なテキストファイルをアップロードしてみて、それが成功するかどうかを確認します。これにより、問題がファイルの内容やサイズにあるのか、それとも基本的な接続や認証にあるのかを切り分けることができます。 - 接続とログインの確認
storlines()
を呼び出す前に、FTPサーバーへの接続 (FTP()
,connect()
) とログイン (login()
) が正常に行われているかを確認してください。これらの前段階でエラーが発生している場合、storlines()
は呼び出されません。 - try-except ブロックでエラーを捕捉する
ftplib.all_errors
を捕捉することで、ftplib
固有のほとんどのエラーを処理できます。from ftplib import FTP, all_errors try: # ... FTP接続と操作 ... except all_errors as e: print(f"FTPエラーが発生しました: {e}") except Exception as e: print(f"予期せぬエラーが発生しました: {e}") finally: if 'ftp' in locals() and ftp: ftp.quit()
基本的なテキストファイルのアップロード
最も基本的な使用例です。ローカルにあるテキストファイルを、指定したファイル名でFTPサーバーにアップロードします。
from ftplib import FTP
# --- 設定情報 ---
FTP_HOST = "your_ftp_host.com" # FTPサーバーのホスト名またはIPアドレス
FTP_USER = "your_username" # FTPユーザー名
FTP_PASS = "your_password" # FTPパスワード
LOCAL_FILE_PATH = "my_document.txt" # ローカルのアップロードしたいファイル
REMOTE_FILE_NAME = "uploaded_doc.txt" # サーバーに保存するファイル名
# -----------------
try:
# 1. FTPオブジェクトを作成し、サーバーに接続
print(f"FTPサーバー {FTP_HOST} に接続中...")
with FTP(FTP_HOST) as ftp:
print(ftp.getwelcome()) # サーバーのウェルカムメッセージを表示
# 2. ログイン
ftp.login(user=FTP_USER, passwd=FTP_PASS)
print("ログインに成功しました。")
# 3. アップロードするファイルをバイナリ読み込みモードで開く
# 'rb'モードで開くことで、改行コードの自動変換をftplibに任せます。
with open(LOCAL_FILE_PATH, 'rb') as fp:
print(f"ファイル '{LOCAL_FILE_PATH}' をアップロード中...")
# 4. storlines() メソッドでファイルをアップロード
# 第一引数はFTPコマンド(STOR <リモートファイル名>)
# 第二引数は開いたファイルオブジェクト
response = ftp.storlines(f"STOR {REMOTE_FILE_NAME}", fp)
print(f"アップロード応答: {response}") # FTPサーバーからの応答を表示
print(f"'{LOCAL_FILE_PATH}' を '{REMOTE_FILE_NAME}' として正常にアップロードしました。")
except Exception as e:
print(f"エラーが発生しました: {e}")
# with ステートメントを使っているので、finallyでftp.quit()を明示的に呼び出す必要はありません
# with ステートメントがブロックを抜けるときに自動的に接続が閉じられます。
ポイント
open(LOCAL_FILE_PATH, 'rb')
のように、必ずバイナリ読み込みモード ('rb'
) でファイルを開きます。これにより、WindowsとLinux/macOS間の改行コードの違いをftplib
が適切に処理します。FTP(FTP_HOST)
をwith
ステートメントで使用すると、処理が完了した後に自動的にFTP接続が閉じられます。
特定のディレクトリへのアップロードと進捗表示
ファイルを特定のサーバーディレクトリにアップロードし、さらに callback
関数を使ってアップロードの進捗状況を表示する例です。
from ftplib import FTP
import os # ファイルサイズの取得に使用
# --- 設定情報 ---
FTP_HOST = "your_ftp_host.com"
FTP_USER = "your_username"
FTP_PASS = "your_password"
LOCAL_FILE_PATH = "large_log_file.txt" # 少し大きめのテキストファイルを想定
REMOTE_DIR = "/remote/logs/" # アップロード先のサーバーディレクトリ
REMOTE_FILE_NAME = "server_log.txt"
# -----------------
# アップロードの進捗を表示するためのコールバック関数
def handle_progress(line):
global uploaded_bytes # グローバル変数としてバイト数を管理
uploaded_bytes += len(line)
# 進捗率を表示(全体のファイルサイズがわかっている場合)
if total_file_size > 0:
progress_percentage = (uploaded_bytes / total_file_size) * 100
print(f"\rアップロード中: {uploaded_bytes} bytes / {total_file_size} bytes ({progress_percentage:.2f}%)", end="")
else:
print(f"\rアップロード中: {uploaded_bytes} bytes", end="")
# グローバル変数の初期化
uploaded_bytes = 0
total_file_size = 0
try:
print(f"FTPサーバー {FTP_HOST} に接続中...")
with FTP(FTP_HOST) as ftp:
ftp.login(user=FTP_USER, passwd=FTP_PASS)
print("ログインに成功しました。")
# リモートディレクトリへ移動
try:
ftp.cwd(REMOTE_DIR)
print(f"ディレクトリ '{REMOTE_DIR}' に移動しました。")
except Exception as e:
print(f"ディレクトリ '{REMOTE_DIR}' が見つからないか、移動できません: {e}")
print("現在のディレクトリにアップロードします。")
REMOTE_DIR = "." # 現在のディレクトリを指す
# ローカルファイルのサイズを取得(進捗表示のため)
total_file_size = os.path.getsize(LOCAL_FILE_PATH)
with open(LOCAL_FILE_PATH, 'rb') as fp:
print(f"ファイル '{LOCAL_FILE_PATH}' をアップロード中...")
# storlines() の第三引数にコールバック関数を指定
response = ftp.storlines(f"STOR {REMOTE_FILE_NAME}", fp, callback=handle_progress)
print(f"\nアップロード応答: {response}") # 応答を表示する前に改行
print(f"'{LOCAL_FILE_PATH}' を '{os.path.join(REMOTE_DIR, REMOTE_FILE_NAME)}' として正常にアップロードしました。")
except Exception as e:
print(f"エラーが発生しました: {e}")
ポイント
- グローバル変数: 進捗を追跡するために
uploaded_bytes
とtotal_file_size
をグローバル変数として使用していますが、より良い設計としては、クラスのインスタンス変数として管理することも考えられます。 callback=handle_progress
:storlines()
のcallback
引数に指定された関数は、ftplib
がファイルから一行読み込み、サーバーに送信するたびに呼び出されます。これにより、進捗バーやアップロードされたバイト数をリアルタイムで表示できます。ftp.cwd(REMOTE_DIR)
: アップロード先のディレクトリが存在しない場合、ftplib.error_perm
などのエラーが発生します。この例では、エラーハンドリングを追加して、ディレクトリが見つからない場合に現在のディレクトリにアップロードするようにフォールバックしています。
ネットワークが不安定な場合や一時的なサーバーの問題が発生した場合に備え、エラーハンドリングを強化し、一定回数リトライするロジックを追加した例です。
from ftplib import FTP, all_errors
import time
# --- 設定情報 ---
FTP_HOST = "your_ftp_host.com"
FTP_USER = "your_username"
FTP_PASS = "your_password"
LOCAL_FILE_PATH = "retry_test_file.txt"
REMOTE_FILE_NAME = "retry_upload.txt"
MAX_RETRIES = 3 # 最大リトライ回数
RETRY_DELAY = 5 # リトライ間の待機時間(秒)
# -----------------
def upload_file_with_retry(ftp_host, ftp_user, ftp_pass, local_path, remote_name, max_retries, retry_delay):
for attempt in range(1, max_retries + 1):
try:
print(f"--- アップロード試行 {attempt}/{max_retries} ---")
with FTP(ftp_host) as ftp:
ftp.login(user=ftp_user, passwd=ftp_pass)
print("ログイン成功。")
with open(local_path, 'rb') as fp:
response = ftp.storlines(f"STOR {remote_name}", fp)
print(f"アップロード応答: {response}")
print(f"'{local_path}' を '{remote_name}' として正常にアップロードしました。")
return True # 成功したらループを終了
except all_errors as e:
print(f"FTPエラーが発生しました: {e}")
if attempt < max_retries:
print(f"リトライします。{retry_delay}秒待機...")
time.sleep(retry_delay)
else:
print("最大リトライ回数に達しました。アップロードに失敗しました。")
return False
except Exception as e:
print(f"予期せぬエラーが発生しました: {e}")
return False
return False # すべてのリトライが失敗した場合
# テスト用のダミーファイルを作成(存在しない場合)
if not os.path.exists(LOCAL_FILE_PATH):
with open(LOCAL_FILE_PATH, 'w') as f:
f.write("This is a test file for retry mechanism.\n")
f.write("Line 2.\n")
f.write("Line 3.\n")
# 関数を呼び出してアップロードを実行
if upload_file_with_retry(FTP_HOST, FTP_USER, FTP_PASS, LOCAL_FILE_PATH, REMOTE_FILE_NAME, MAX_RETRIES, RETRY_DELAY):
print("\nファイルアップロード処理が正常に完了しました。")
else:
print("\nファイルアップロード処理が失敗しました。")
time.sleep()
: リトライの間に一定時間待機することで、サーバーへの負荷を減らし、一時的なネットワークの問題が解決するのを待ちます。- リトライループ:
for attempt in range(...)
ループを使って、指定された回数だけアップロード処理を試行します。 ftplib.all_errors
:ftplib
関連のすべてのエラーを捕捉するための便利な例外クラスです。
ftplib.FTP.storbinary() の使用
storlines()
はテキストファイル(ASCIIモード)のアップロードに適していますが、storbinary()
はバイナリファイル(画像、動画、ZIPファイルなど)のアップロードに適しています。ただし、テキストファイルをバイナリモードでアップロードしたい場合にも使用できます。
特徴
- シグネチャ
storbinary(cmd, fp, blocksize=8192, callback=None)
cmd
:STOR filename
またはAPPE filename
(追記) などのFTPコマンド。fp
: バイナリ読み込みモード ('rb'
) で開かれたファイルオブジェクト。blocksize
: 一度に読み書きするバイト数。大きいほど高速になる可能性がありますが、メモリ使用量も増えます。callback
: 進捗表示用のコールバック関数。
- 動作
ファイルの内容をバイト列として読み込み、FTPサーバーにそのまま送信します。改行コードの自動変換は行いません。 - 用途
バイナリファイルのアップロードが主ですが、テキストファイルをバイト列として扱い、改行コード変換を抑制したい場合にも使用できます。
storbinary() を使ったテキストファイルのアップロード例
from ftplib import FTP
FTP_HOST = "your_ftp_host.com"
FTP_USER = "your_username"
FTP_PASS = "your_password"
LOCAL_FILE_PATH = "my_plain_text.txt" # ローカルのテキストファイル
REMOTE_FILE_NAME = "uploaded_binary_text.txt" # サーバー上のファイル名
try:
with FTP(FTP_HOST) as ftp:
ftp.login(user=FTP_USER, passwd=FTP_PASS)
print("ログインに成功しました。")
# storbinary() を使ってテキストファイルをアップロードする場合も、'rb' で開きます。
# storlines() とは異なり、改行コードの自動変換は行われません。
# ただし、最近のftplibではstorlines()も内部で'rb'を推奨しているため、
# どちらを使うかは、改行コード変換の有無を意識するかどうかで選択できます。
with open(LOCAL_FILE_PATH, 'rb') as fp:
print(f"ファイル '{LOCAL_FILE_PATH}' を storbinary() でアップロード中...")
response = ftp.storbinary(f"STOR {REMOTE_FILE_NAME}", fp)
print(f"アップロード応答: {response}")
print(f"'{LOCAL_FILE_PATH}' を '{REMOTE_FILE_NAME}' として正常にアップロードしました (storbinary)。")
except Exception as e:
print(f"エラーが発生しました: {e}")
storlines() と storbinary() の使い分け
storbinary()
: バイナリファイル、またはテキストファイルをバイト列としてそのまま転送したい場合(改行コード変換が不要な場合)storlines()
: テキストファイル(改行コードの自動変換が必要な場合)
実際には、Python 3ではstorlines()
でも'rb'
でファイルを開くのが推奨されるため、多くのテキストファイルアップロードのシナリオではstorlines()
とstorbinary()
の挙動上の違いは小さくなっています。しかし、storbinary()
はblocksize
を指定できる点で、大きなファイルの転送性能を調整する柔軟性があります。
ftplib
はPython標準ライブラリであり、基本的なFTP機能を提供しますが、より高レベルな機能(例: ファイルの存在チェック、ディレクトリの再帰的なアップロード、セッション管理、エラーハンドリングの簡素化)や、よりモダンな接続方法(例: FTPS, SFTP)が必要な場合は、外部ライブラリの利用が非常に有効です。
a. paramiko
(SFTPに特化)
paramiko
は、SSHv2プロトコルを実装しており、SFTP(SSH File Transfer Protocol)を扱うためのデファクトスタンダードともいえるライブラリです。SFTPはFTPとは異なるプロトコルですが、セキュアなファイル転送が必要な場合に検討する価値があります。
特徴
- 依存関係
pycryptodome
(またはpycrypto
) などの暗号ライブラリに依存します。 - 機能
ファイルのアップロード/ダウンロード、ディレクトリ操作、パーミッション変更など、豊富な機能を提供します。 - セキュリティ
SSHの暗号化を利用するため、FTPよりもはるかにセキュアです。
インストール
pip install paramiko
paramiko を使ったSFTPファイルアップロード例
import paramiko
# --- 設定情報 ---
SFTP_HOST = "your_sftp_host.com" # SFTPサーバーのホスト名
SFTP_PORT = 22 # SFTPのデフォルトポートは22
SFTP_USER = "your_username"
SFTP_PASS = "your_password"
# または、キーファイル認証
# PRIVATE_KEY_PATH = "/path/to/your/private_key"
LOCAL_FILE_PATH = "my_secure_document.txt"
REMOTE_FILE_PATH = "/remote/path/secure_doc.txt"
# -----------------
try:
with paramiko.SSHClient() as client:
client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 初回接続時にホストキーを追加
print(f"SFTPサーバー {SFTP_HOST}:{SFTP_PORT} に接続中...")
# パスワード認証
client.connect(hostname=SFTP_HOST, port=SFTP_PORT, username=SFTP_USER, password=SFTP_PASS)
# または、キーファイル認証
# client.connect(hostname=SFTP_HOST, port=SFTP_PORT, username=SFTP_USER, key_filename=PRIVATE_KEY_PATH)
print("SFTP接続に成功しました。")
with client.open_sftp() as sftp:
print(f"ファイル '{LOCAL_FILE_PATH}' を '{REMOTE_FILE_PATH}' にアップロード中...")
sftp.put(LOCAL_FILE_PATH, REMOTE_FILE_PATH)
print("アップロードが正常に完了しました。")
except Exception as e:
print(f"SFTP接続またはアップロード中にエラーが発生しました: {e}")
ポイント
paramiko
はより高レベルなAPIを提供し、ファイルの転送がput()
メソッド一つで完結します。- SFTPはFTPとは根本的に異なるプロトコルであるため、SFTPサーバーにしか接続できません。
b. ftputil
(より高レベルなFTPラッパー)
ftputil
は ftplib
の上に構築された高レベルなFTPクライアントライブラリで、ローカルファイルシステムとFTPサーバーのファイルシステムをより一貫性のある方法で扱えるように設計されています。
特徴
- 機能
ディレクトリの再帰的なアップロード/ダウンロード、ファイルの同期、ファイルのタイムスタンプ保持など、多くの便利な機能があります。 - 堅牢性
内部で再接続やエラーハンドリングを自動的に行い、より堅牢なFTPセッションを提供します。 - 使いやすさ
os
モジュールやshutil
モジュールに似たAPIを提供し、直感的に使用できます。
インストール
pip install ftputil
ftputil を使ったファイルアップロード例
import ftputil
# --- 設定情報 ---
FTP_HOST = "your_ftp_host.com"
FTP_USER = "your_username"
FTP_PASS = "your_password"
LOCAL_FILE_PATH = "my_ftputil_doc.txt"
REMOTE_FILE_PATH = "/remote/path/ftputil_doc.txt"
# -----------------
try:
print(f"FTPサーバー {FTP_HOST} に接続中 (ftputil)...")
# ftputil.FTPHost は with ステートメントで自動的に接続を閉じます
with ftputil.FTPHost(FTP_HOST, FTP_USER, FTP_PASS) as host:
print("ログインに成功しました。")
print(f"ファイル '{LOCAL_FILE_PATH}' を '{REMOTE_FILE_PATH}' にアップロード中...")
# upload() メソッドを使用。バイナリ転送がデフォルト
host.upload(LOCAL_FILE_PATH, REMOTE_FILE_PATH)
print("アップロードが正常に完了しました。")
except Exception as e:
print(f"FTP接続またはアップロード中にエラーが発生しました: {e}")
upload()
メソッド一つでファイル転送が完了するため、ftplib
のopen()
やstorlines()
/storbinary()
の組み合わせよりもコードが簡潔になります。ftputil.FTPHost
は自動的にバイナリモードでファイルを転送します。テキストファイルをアップロードする場合でも、内部で適切に処理されます。
代替方法 | 主な用途 | 特徴 | セキュリティ |
---|---|---|---|
ftplib.FTP.storbinary() | バイナリファイル、バイト列としてのテキスト | ftplib 標準機能、改行コード変換なし、blocksize 指定可能 | 低 |
paramiko (SFTP) | セキュアなファイル転送 (SSH経由) | 高度なセキュリティ、SSHベース、パスワード/キー認証、SFTP機能が豊富 | 高 |
ftputil | 高レベルなFTP操作 | ftplib のラッパー、使いやすいAPI、堅牢、再帰的アップロード/同期など | 低 (FTPのまま) |
- より高レベルなFTP操作や堅牢性
ftputil
が非常に便利です。 - セキュリティが最優先
paramiko
を使ったSFTPを検討してください。FTPサーバーがSFTPに対応している必要があります。 - バイナリファイルのアップロード
ftplib.FTP.storbinary()
を使用すべきです。 - シンプルなFTPテキストファイルアップロード
ftplib.FTP.storlines()
またはftplib.FTP.storbinary()
('rb'
モードでファイルを開く) が適切です。