web-dev-qa-db-ja.com

Openpyxlが読み取り専用モードでExcelブックを閉じない

PythonでExcelファイルを読み取れるようにしたい、Pythonスクリプトを実行したまま、読み取りが完了した後、別のプロセスでExcelファイルを編集できるようにしたい。 python 2.7とopenpyxlを使用しています。

現在は次のようになっています:

from openpyxl import load_workbook

def get_Excel_data():
    OESwb = load_workbook(filename = OESconfigFile, data_only=True, 
                          read_only=True)
    ws = OESwb.get_sheet_by_name('MC01')
    aValue = ws['A1'].value
    return aValue

val = get_Excel_data()

関数を実行した後、Pythonもう。

スクリプトからファイルを閉じるにはどうすればよいですか? OESwb.close()を試しましたが、「 'Workbook' object has no attribute 'close'」というエラーが表示されます。私は this post を見つけましたが、役に立たないようです。

編集:OESwb.save( 'filename.xlsx')は機能するようですが、read_only = Falseの場合のみです。ただし、ファイルを閉じても読み取り専用モードであることが理想的です。 load_workbookの終了後にファイルを閉じる必要があるため、これはopenpyxlのバグのようです。

7
wordsforthewise
wb._archive.close()

Use_iteratorでも動作します。

12
user5859387

厳格な理由で、stackoverflowを使用すると回答を投稿できますが、コメントまたは投票するのに十分な「担当者」がいないため、ここにあります。

受け入れられたwb._archive.close()の答えは私にとってうまくいきませんでした。これはおそらく、読み取り専用モードを使用しているためです。 「通常」モードの場合は問題なく動作する可能性があります。

bmiller の答えは、私にとっても有効な唯一の答えです。

with open(xlsx_filename, "rb") as f:
    in_mem_file = io.BytesIO(f.read())

wb = load_workbook(in_mem_file, read_only=True)

そして、彼が言ったように、読み取り専用のみを使用するよりも、open()でロードする方が高速です

Bmillerの答えに基づいた私の作業コード:

import openpyxl
import io

xlsx_filename=r'C:/location/of/file.xlsx')
with open(xlsx_filename, "rb") as f:
    in_mem_file = io.BytesIO(f.read())

wb = openpyxl.load_workbook(in_mem_file, read_only=True)
12
Patrick Conwell

私は、読み取り専用モードでxlsxファイルを閉じるためにこれらのすべての解決策を試しましたが、どれもその仕事をしていないようです。私は最終的にメモリ内ファイルを使用することになりました:

with open(xlsx_filename, "rb") as f:
    in_mem_file = io.BytesIO(f.read())

wb = load_workbook(in_mem_file, read_only=True)

読み込みが速くなることもあり、何かを閉じることを心配する必要はありません。

8
bmiller

最新の情報については、openpyxl 2.4.4+がWorkbook.close()メソッドを提供しています。以下は参考資料です。

http://openpyxl.readthedocs.io/en/stable/changes.html?highlight=close#id86
https://bitbucket.org/openpyxl/openpyxl/issues/67

4
Leonard2

私もこれが問題であることに気付き、ワークブックにcloseメソッドがないのは奇妙だと思います。

私が思いついた解決策は、スプレッドシートを読むたびにコードに意味のない保存を行わないように、ファイルを「閉じる」コンテキストマネージャでした。

@contextlib.contextmanager
def load_worksheet_with_close(filename, *args, **kwargs):
    '''
    Open an openpyxl worksheet and automatically close it when finished.
    '''
    wb = openpyxl.load_workbook(filename, *args, **kwargs)
    yield wb
    # Create path in temporary directory and write workbook there to force
    # it to close
    path = os.path.join(tempfile.gettempdir(), os.path.basename(filename))
    wb.save(path)
    os.remove(path)

それを使用するには:

with load_worksheet_with_close('myworkbook.xlsx') as wb:
    # Do things with workbook
2

OESwb._archive.close()を使用します。これにより、'read_only=True'モードで開いたままにしていた追加のZipFileファイルハンドルが閉じます。クローズ後、OESwbからこれ以上データを読み取ることができなくなったことに注意してください。また、これは回避策ではなく、_archiveは将来のバージョンで削除される可能性があることに注意してください。

2
stovfl

閉じるには、ファイルを保存する必要があると思います。

OESwb.save('filename.xlsx')

お役に立てれば。

1
jharrison12

あなたが試すことができます:

wb = None

リソースを解放し、同じまたは他の変数に、必要に応じてすぐに再度ロードします。

0
MASR