LoginSignup
3
3

More than 3 years have passed since last update.

【Python】ファイルをオンメモリで生成してFTPで転送する

Last updated at Posted at 2020-12-11

FTP(SFTP)による高頻度なファイル転送を実装する機会があったので、
備忘録も兼ねてまとめました。

PythonでのFTP

PythonにはFTP周りのインタフェースを提供するライブラリftplibがあり、
これを用いることでFTPサーバとの通信プログラムを簡単に実装することができます。

ローカルファイルを転送する場合はこんな感じ:

ftptransfer.py
from ftplib import FTP

def main():
    # 接続
    ftp = FTP("example.com", "username", passwd = "password")

    # FTP.storlinesにファイルオブジェクトを渡す
    with open("test.txt", "rb") as f:
        ftp.storlines("STOR ./test.txt", f)

    # 切断
    ftp.quit()

if __name__ == "__main__":
    main()

しかし、この方法ではプログラム実行中に出力されたメモリ上のデータを転送することができません。
いちいちファイルに出力するのは冗長ですし、何よりストレージへの負荷がすごそうです。

オンメモリでファイルオブジェクトを作る

そこで、StringIOおよびBytesIOを用いてストリームを生成し、ftplibに渡す方法を考えます。

引用: Pythonドキュメント 「io --- ストリームを扱うコアツール

インメモリー ストリーム

str や bytes-like オブジェクト を、読み書き可能なファイルのように扱うことができます。 StringIO は文字列に対して、テキストモードで開かれたファイルのように使うことができます。 BytesIO はバイナリーモードで開いたファイルのように扱うことができます。この2つのクラスは、読み書き可能で、ランダムアクセス可能です。

storlinesはバイナリモードで開いたファイルのオブジェクトを渡す必要があるので、今回はio.BytesIOを使用します。

BytesIOTest.py
import io

def main():
    # io.BytesIOオブジェクトを生成
    bytesIO = io.BytesIO(bytes("Hello, World!!", encoding="utf-8"))
    print(type(bytesIO))

    # ファイルオブジェクトのように操作する
    with bytesIO as b:
        print(b.readlines())

if __name__ == "__main__":
    main()

# 実行結果
# <class '_io.BytesIO'>
# [b'Hello, World!!']

BytesIOオブジェクトが生成され、with文で読むとbytesが返ってきます。

ftplibに渡して転送する

では、このBytesIOオブジェクトをstorlinesに渡してみます。

sendOnMemoryFile.py
import io
from ftplib import FTP

def main():
    # io.BytesIOでファイルっぽいものを作り、
    bytesIO = io.BytesIO(bytes("Hello, World!!", encoding="utf-8"))
    print(type(bytesIO))

    # FTP.storlinesに渡して転送する
    ftp = FTP("example.com", "username", passwd = "password")
    ftp.storlines("STOR ./test.txt", bytesIO)

    ftp.quit()

if __name__ == "__main__":
    main()

実行後、サーバをのぞくと…

[username@example.com ~]$ cat test.txt 
Hello, World!!

記述した文字列が書き込まれたファイルtest.txtが作成されていることがわかります。

まとめ

ここまで読んでいただきありがとうございました。

まとめで言うのもアレですが、こんな面倒なことをするよりHTTPSを使うべきだと思います。
FTPはFile Transfer Protocolなので。

ではまた!

3
3
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3