I use a self-written script to upload data from a legacy product through ods documents.

Current implementation:

import ezodf from . import db ezodf.config.set_table_expand_strategy('all') current_spreadsheet = ezodf.opendoc(filename='./table1.ods') current_table = current_spreadsheet.sheets[-1] for row_num in range(current_table.nrows()): db.session.add( Model_1( id=current_table['a%s' % row_num].value, name=current_table['b%s' % row_num].value ) ) db.session.commit() 

So, as the tables are quite a decent amount and they have a different structure, I would like to brush the code like this:

 with ezodf.opendoc(filename='./table1.ods') as spreadsheet: with spreadsheet.sheets[-1] as table: for row_num in range(table.nrows()): db.session.add( Model_1( id=table['a%s' % row_num].value, name=table['b%s' % row_num].value ) ) 

But when performing the second option, I get the following:

 File "uploader.py", line 36, in <module> with ezodf.opendoc(filename='./table_1.ods') as spreadsheet: AttributeError: __exit__ 

How to get around / catch this error?

 ezodf - 0.3.2 lxml - 3.7.2 python - 3.5 

    1 answer 1

    According to PEP-0343, the with ... construct expects an object in which the following methods are implemented: __enter__() and __exit__() :

    In this PEP, context managers provide __enter__() and __exit__() methods.

    The object returned by ezodf.opendoc(...) does not implement the __exit__() ezodf.opendoc(...) method, so with ... it will not work. You can certainly try to write your class inheriting it from the ezodf classes, but in my opinion this is a bust ...

    This object does not even have a .close() method, so if you do not change the documents, you can simply use the same variable for different documents. If you change, do not forget to save the changes with .save(...) or .saveas(...)

    You can arrange the processing of documents in the form of a function.

    Example:

     def process_sheet(filename, sheet_no=-1): sheet = ezodf.opendoc(filename=filename) tab = sheet.sheets[sheet_no] for row in tab.rows(): # process data here for cell in row: print(cell.value, end='\t') print() 

    Test:

     xyz 10.0 20.0 30.0 40.0 50.0 60.0 
    • Thank you, go read PEP-0343 and look for other libraries to read ods, which can concisely describe ~ 20 models. - Tihon