PythonでFTPアップロードを行う方法

PythonでFTPアップロードを行う方法をご紹介します。

条件

  • Python 3.7.0

サンプルソース

以下がFTP接続して指定ファイルをアップロードするサンプルです。

import ftplib
from logging import getLogger, StreamHandler, Formatter, DEBUG


## ログ出力設定
logger = getLogger("FTP Test")
logger.setLevel(DEBUG)
stream_handler = StreamHandler()
stream_handler.setLevel(DEBUG)
formatter = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)

## 接続先ホスト
HOST = 'XXX.com'
PORT = 21
USER = 'userName'
PASSWORD = 'password'
DIRECTORY = 'test'

## アップロードファイル名
FILE_NAME = 'test.jpg'


## FTP接続、ファイルアップロード
logger.debug('== Start FTP ==')
with FTP() as ftp:
    try:
        ftp.connect(HOST, PORT)   # ホスト、ポートを指定して接続
        ftp.login(USER, PASSWORD) # ユーザID、パスワードを指定してログイン
        ftp.cwd(DIRECTORY)        # 指定のディレクトリに移動
        with open(FILE_NAME, 'rb') as f:
            ftp.storbinary('STOR ' + FILE_NAME, f) # 対象ファイルをアップロード
    except ftplib.all_errors as e:
        logger.error('FTP error = %s' % e)
    else:
        logger.debug('FTP success.')
logger.debug('== End FTP ==')

処理の流れ

処理の流れは以下の通りです。

  1. 対象ホストに接続
  2. 対象ホストにログイン
  3. 指定のディレクトリに移動
  4. 対象ファイルをアップロード

解説

  • ftplibを用いてFTP接続を行っています。
  • withと共に使用することで、明示的にquit()を記述しなくてもftp接続を閉じることが出来ます。
  • ftp.connectでは、「接続先ホスト」と「ポート」を指定して接続を行っています。
  • ftp.loginでは、「ユーザID」と「パスワード」を指定してログインを行っています。
  • ftp.storbinaryでは、対象ファイルをバイナリ転送モードでアップロードしています。
    (バイナリ転送モードは、画像などのバイナリファイル取得や、テキストファイルの改行コード変換を行わずに取得したい場合に使用します。)
  • except ftplib.all_errors as e:では、FTP接続で発生する全ての例外を捕獲できます。
    詳細エラーは以下のような種類があります。

    • ftplib.error_reply:サーバから想定外の応答があったときに送出される例外。
    • ftplib.error_temp:一時的エラーを表すエラーコード(400–499の範囲の応答コード)を受け取った時に発生する例外。
    • ftplib.error_perm:永久エラーを表すエラーコード(500–599の範囲の応答コード)を受け取った時に発生する例外。
    • ftplib.error_proto:File Transfer Protocol の応答仕様に適合しない、すなわち1–5の数字で始まらない応答コードをサーバから受け取った時に発生する例外。

サーバー側の設定がおかしい場合の回避策

FTP接続を行うサーバー側の設定がおかしくて、「FTP接続は出来るけれどもデータが取得できない」という状況に出くわす場合があります。

詳細は以下の記事をご参照ください。

FTPで接続は出来るがデータ取得が出来ない場合の対応

回避策ソース

以下のような記述を追記します。

from ftplib import FTP


## ネットワーク設定問題の回避策
_old_makepasv = FTP.makepasv
def _new_makepasv(self):
    HOST, PORT = _old_makepasv(self)
    HOST = self.sock.getpeername()[0]
    return HOST, PORT
FTP.makepasv = _new_makepasv

回避策を含めた全体ソース

全体のソースは以下のようになります。

from ftplib import FTP
import ftplib
from logging import getLogger, StreamHandler, Formatter, DEBUG


## ログ出力設定
logger = getLogger("FTP Test")
logger.setLevel(DEBUG)
stream_handler = StreamHandler()
stream_handler.setLevel(DEBUG)
formatter = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)

## 接続先ホスト
HOST = 'XXX.com'
PORT = 21
USER = 'userName'
PASSWORD = 'password'
DIRECTORY = 'test'

## アップロードファイル名
FILE_NAME = 'test.jpg'


## ネットワーク設定がおかしい場合の回避策
_old_makepasv = FTP.makepasv
def _new_makepasv(self):
    HOST, PORT = _old_makepasv(self)
    HOST = self.sock.getpeername()[0]
    return HOST, PORT
FTP.makepasv = _new_makepasv


## FTP接続、ファイルアップロード
logger.debug('== Start FTP ==')
with FTP() as ftp:
    try:
        ftp.connect(HOST, PORT)   # ホスト、ポートを指定して接続
        ftp.login(USER, PASSWORD) # ユーザID、パスワードを指定してログイン
        ftp.cwd(DIRECTORY)        # 指定のディレクトリに移動
        with open(FILE_NAME, 'rb') as f:
            ftp.storbinary('STOR ' + FILE_NAME, f) # 対象ファイルをアップロード
    except ftplib.all_errors as e:
        logger.error('FTP error = %s' % e)
    else:
        logger.debug('FTP success.')
logger.debug('== End FTP ==')

参考

Python:ftplib — FTPプロトコルクライアント

https://docs.python.org/ja/3/library/ftplib.html

PythonでFTPアップロードを行う方法” に対して1件のコメントがあります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です