2017/04/06更新

[Python] PythonからFTPを実行する

このエントリーをはてなブックマークに追加            

こんにちは、@yoheiMuneです。
今日はftplibという標準モジュールを使って、PythonからFTPを行う方法をブログに残したいと思います。

画像

目次




FTP環境の準備(必要あれば)

テスト用にFTPサーバーを作成します。ここではDockerを使いたいと思います(DockerについてはDockerに入門する(インストール、OSイメージ入手、コンテナ起動、コンテナ管理)をご参照ください)。

FTPサーバーとして、以下のDockerイメージを利用します。
https://github.com/stilliard/docker-pure-ftpd

そして以下のようにセットアップを行い、FTPサーバーを構築します。
# Dockerイメージをダウンロード
$ docker pull stilliard/pure-ftpd:hardened

# イメージからインスタンスを起動
docker run -d --name ftpd_server -p 21:21 -p 30000-30009:30000-30009 -e "PUBLICHOST=localhost" stilliard/pure-ftpd:hardened

# インスタンスにログイン
docker exec -it ftpd_server /bin/bash

# FTPユーザーとして「bob」を作成する.
# ここでは、パスワードに「password」という文字列を設定しました.
pure-pw useradd bob -f /etc/pure-ftpd/passwd/pureftpd.passwd -m -u ftpuser -d /home/ftpusers/bob
Password:  # password
その後、別のターミナルを立ち上げて以下のコマンドでログインできればOKです。
$ ftp -p localhost 21
Name: bob
Password: password
ftp>
お試し環境については、既に既存のFTPサーバーがあればそちらでもOKです。



PythonからFTPを利用する

ここから本題ですが、PythonからFTPを利用するにはftplibパッケージを利用します。これを用いることで、FTPコマンドベースでの利用が可能となります。

FTP接続

以下のようにモジュールを読み込んで接続することができます。
# モジュールのインポート.
from ftplib import FTP

# FTP接続.
ftp = FTP(
    "localhost",
    "bob",
    passwd="password"
)


ファイルのアップロード(テキスト)

テキストベースでのファイルのアップロードにはftp.storlinesを使います。
# ファイルのアップロード(テキスト).
with open("a.txt", "rb") as f:  # 注意:バイナリーモード(rb)で開く必要がある
    ftp.storlines("STOR /aa.txt", f)


ファイルのアップロード(バイナリー)

バイナリーのアップロードにはftp.storbinaryを使います。
# ファイルのアップロード(バイナリー).
with open("b.txt.zip", "rb") as f:
    ftp.storbinary("STOR /bb.zip", f)


ファイルのダウンロード(テキスト)

テキストデータのダウンロードにはftp.retrlinesを使います。
# ファイルの取得(テキスト).
with open("b.txt", "w") as f:
    ftp.retrlines("RETR /aa.txt", f.write)


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

バイナリデータのダウンロードにはftp.retrbinaryを使います。
# ファイルの取得(バイナリー).
with open("bb.txt.zip", "wb") as f:
    ftp.retrbinary("RETR /bb.zip", f.write)


ディレクトリを作成

ftp.mkdでディレクトリを作成できます。
# ディレクトリ作成.
ftp.mkd("subdir")


ディレクトリの削除

ftp.rmdでディレクトリを削除できます。
# ディレクトリ削除
ftp.rmd("subdir")


パーミッションの変更

ftp.sendcmdを使って、FTPサーバー上で任意のコマンドを実行します。ここではchmodコマンドを実行して権限を変更しています。
# 権限の変更.
ftp.sendcmd("SITE CHMOD 604 /aa.txt")


ファイル一覧の取得(シンプル)

ftp.nlstを使うと、ファイル一覧を取得できます。
# ファイル一覧の取得.
items = ftp.nlst(".")
print(items) # ['aa.txt', 'bb.zip', 'subdir']


ファイル一覧の取得(標準出力)

ftp.dirをつかうと、ls -lのような形式で表示してくれます。
# ファイル一覧を標準出力に表示.
ftp.dir(".")
"""
-rw-r--r--    1 1000       ftpgroup           11 Apr  3 02:44 aa.txt
-rw-r--r--    1 1000       ftpgroup          165 Apr  3 02:44 bb.zip
drwxr-xr-x    2 1000       ftpgroup         4096 Apr  3 02:44 subdir
"""


ファイル一覧の取得(詳細に)

ftp.mlsdをつかうと、ファイル一覧をファイルの詳細とともに取得することができます。この詳細情報でパーミッションや、ディレクトリかファイルか判断、などができます。
from pprint import pprint

# ファイルの情報を取得.
items = ftp.mlsd()
for filename, opt in items:
    print("---------------")
    print(filename)
    pprint(opt)
"""
---------------
.
{'modify': '20170403024424',
 'sizd': '4096',
 'type': 'cdir',
 'unique': 'fe02g202315',
 'unix.gid': '1000',
 'unix.mode': '0755',
 'unix.uid': '1000'}
---------------
..
{'modify': '20170403024424',
 'sizd': '4096',
 'type': 'pdir',
 'unique': 'fe02g202315',
 'unix.gid': '1000',
 'unix.mode': '0755',
 'unix.uid': '1000'}
---------------
aa.txt
{'modify': '20170403024424',
 'size': '11',
 'type': 'file',
 'unique': 'fe02g20231b',
 'unix.gid': '1000',
 'unix.mode': '0644',
 'unix.uid': '1000'}
---------------
bb.zip
{'modify': '20170403024424',
 'size': '165',
 'type': 'file',
 'unique': 'fe02g20231c',
 'unix.gid': '1000',
 'unix.mode': '0644',
 'unix.uid': '1000'}
---------------
subdir
{'modify': '20170403024424',
 'sizd': '4096',
 'type': 'dir',
 'unique': 'fe02g20231d',
 'unix.gid': '1000',
 'unix.mode': '0755',
 'unix.uid': '1000'}
"""


その他に

その他にも、ファイルの削除や名前変更などもありますので、詳しくは以下をご覧ください。
https://docs.python.jp/3/library/ftplib.html



参考資料

以下の記事を参照しました、ありがとうございます。

21.13. ftplib — FTPプロトコルクライアント — Python 3.6.1 公式ドキュメント

Python 3でFTPを使ったファイルのアップロード - anon21's Blog

[python]ftplibでgetとかputとか - 記録(e_c_e_t)

Python ftplibでファイルをFTP GETする | いいわけブログ


最後に

PythonでFTPも簡単にできていいですね。コマンドもローレベルに使えるので色々と応用ができそうです。Pythonについてはもっともっと学んで、色々とブログに書きたい今日この頃です。

最後になりますが本ブログでは、Python・Linux・Node.js・フロントエンド・インフラ・Go言語・開発関連・Swift・Java・機械学習など雑多に情報発信をしていきます。自分の第2の脳にすべく、情報をブログに貯めています。気になった方は、本ブログのRSSTwitterをフォローして頂けると幸いです ^ ^。

最後までご覧頂きましてありがとうございました!





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。