0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

NamedTemporaryFileにおけるアップロード時のclosed file関連のバグ

Posted at

本記事で扱っている内容はNamedTemporaryFileのバグです。

概要

NamedTemporaryFileでDLしたファイルをS3へアップロードした後、再度参照しようとした際にclosed file関連でエラーが出たので、その時の対処法を記載する。

困った事

以下の手順で開発を進めていたが、手順4の箇所で以下のエラーに遭遇し解決策を模索していた。

ValueError: I/O operation on closed file
ValueError: seek of closed file
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpoirwooqn.xlsm'
  1. S3からxlsmをDL
  2. 情報を転記
  3. S3へxlsmをUP
  4. xlsmを参照して情報を修正
  5. S3へxlsmをUP(3とは独立)

元のソース

with tempfile.NamedTemporaryFile(mode='wb+', suffix='.xlsm') as tf:
    # S3からテンプレートファイルをダウンロード
    s3 = S3()
    s3.download_report_file('template_hoge/hoge/', 'template', tf)

    # テンプレートファイルにデータを入力してファイルを作成
    for file_type in ['xlsm', 'xlsx']:
        if file_type == 'xlsm':
            wb = openpyxl.load_workbook(tf.name, keep_vba=True)
            # ファイルに情報転記(省略)
            wb.save(tf.name)
            # ファイルをS3へアップロード
            tf.seek(0)
            s3.upload_report_file('hoge/hoge/', 'hoge', tf)
        elif file_type == 'xlsx':
            wb = openpyxl.load_workbook(tf.name)
            # ファイルに情報転記(省略)
            wb.save(tf.name)
            # ファイルをS3へアップロード
            tf.seek(0)
            s3.upload_report_file('hoge/hoge/', 'hoge', tf)

解決策

class NonCloseableBufferedReader(BufferedReader):
    def close(self):
        self.flush()

with tempfile.NamedTemporaryFile(mode='wb+', suffix='.xlsm') as tf:
    # S3からテンプレートファイルをダウンロード
    s3 = S3()
    s3.download_report_file('template_hoge/hoge/', 'template', tf)

    # テンプレートファイルにデータを入力してファイルを作成
    for file_type in ['xlsm', 'xlsx']:
        if file_type == 'xlsm':
            wb = openpyxl.load_workbook(tf.name, keep_vba=True)
            # ファイルに情報転記(省略)
            wb.save(tf.name)
            # ファイルをS3へアップロード
            tf.seek(0)
                        buffer = NonCloseableBufferedReader(tf)
            s3.upload_report_file('hoge/hoge/', 'hoge', buffer)
            buffer.detach()
            assert not tf.closed
        elif file_type == 'xlsx':
            wb = openpyxl.load_workbook(tf.name)
            # ファイルに情報転記(省略)
            wb.save(tf.name)
            # ファイルをS3へアップロード
            tf.seek(0)
            s3.upload_report_file('hoge/hoge/', 'hoge', tf)

回避策の説明

近日公開

0
1
0

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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?