Python win32com.client и оператор "with" - PullRequest
0 голосов
/ 17 ноября 2018

Добрый день,

Я пишу некоторые сценарии ETL на Python и в настоящее время использую win32com.client для открытия и обновления некоторых подключений к данным в Excel.

У меня такой вопрос: должен ли я использовать с оператором для открытия / закрытия "Excel.Application" как такового

import win32com.client
xl = win32com.client.DispatchEx("Excel.Application")

def wb_ref(file):
    xl.DisplayAlerts = False
    with xl.workbooks.open(file) as wb:
        wb.RefreshAll()
        wb.Save()

wb_ref('C:/Users/smugs/Documents/folder_a/workbooks/test.xlsx')

Когда я пытался это сделать, возникает исключение, поэтому я явно не правильно его использую.

Traceback (most recent call last):
  File "C:/Users/smugs/Documents/Python Scripts/Work/km_jobs/utils/xl_conv.py", line 32, in <module>
    wb_ref( 'C:/Users/smugs/Documents/folder_a/workbooks/test.xlsx')
  File "C:/Users/smugs/Documents/Python Scripts/Work/km_jobs/utils/xl_conv.py", line 11, in wb_ref
    with xl.workbooks.open(file) as wb:
AttributeError: __enter__

Или мне нужно явно вызвать команду закрытия

def wb_ref(file):
    xl.DisplayAlerts = False
    wb = xl.workbooks.open(file)
    wb.RefreshAll()
    wb.Save()
    wb.Close()

wb_ref('C:/Users/smugs/Documents/folder_a/workbooks/test.xlsx')

Второй пример - это то, что я использовал, и оно работает. Я думаю, мне просто интересно, каков более питонический способ написания вышеуказанной функции.

(fyi - впервые спрашивающий, давний читатель)

1 Ответ

0 голосов
/ 18 ноября 2018

Вы получаете ошибку AttributeError: __enter__, потому что xl.workbooks.open не является диспетчером контекста , и поэтому он не поддерживает оператор with.

Если вы хотите использоватьоператор with в вашем коде, вы можете использовать функцию закрытия из модуля contextlib в стандартной библиотеке, например:

from contextlib import closing

def wb_ref(file):
    xl.DisplayAlerts = False
    with closing(xl.workbooks.open(file)) as wb:
        wb.RefreshAll()
        wb.Save()

contextlib.closingавтоматически вызовет close для объекта, переданного ему, когда код в блоке with завершит выполнение.

...