xlwings: как определить, вызывается ли функция Python из модуля VBA? - PullRequest
0 голосов
/ 22 июня 2019

Положение

Пакет xlwings предоставляет удобный способ вызова функций python из модуля Excel VBA . В документации xlwings приведен следующий базовый пример:

Запишите приведенный ниже код в модуль VBA.

Sub HelloWorld()
    RunPython ("import hello; hello.world()")
End Sub

Это вызывает следующий код в hello.py:

# hello.py
import numpy as np
import xlwings as xw

def world():
    wb = xw.Book.caller()
    wb.sheets[0].range('A1').value = 'Hello World!'

Попытка прямого запуска функции python world() (вместо вызова ее из Excel VBA) выдает следующее сообщение об ошибке:

Исключение: Book.caller () не должен вызываться напрямую. Звоните через Excel или сначала установите псевдоним с помощью Book.set_mock_caller ().

Вопрос

Я бы хотел изменить функцию world() так, чтобы она вызывала пользовательское исключение вместо непосредственного запуска. Чтобы достичь этого, мне сначала нужно программно определить, выполняется ли функция world() напрямую или вызывается из Excel VBA (по крайней мере, я так думаю). Как я мог это сделать?

1 Ответ

1 голос
/ 22 июня 2019

Вы можете поймать исключение и затем поднять свое собственное:

def world():
    try:
        wb = xw.Book.caller()
    except Exception:
        raise CustomException(custom_message)
    wb.sheets[0].range('A1').value = 'Hello World!'

Вы обеспокоены тем, что Exception является слишком общим, и это правильно. Но это вина Xlwings, а не твоя. Если он поднимает общий Exception, это все, что вам осталось поймать. Вы можете проверить сообщение об исключении, чтобы убедиться, что вы не перехватываете неправильное исключение, но это будет хрупким Сообщения об ошибках обычно не документированы и не должны рассматриваться как общедоступный стабильный API.

В качестве альтернативы вы можете решить проблему там, где проблема, исходный код xlwings , и заставить его делать то, что мне кажется правильным: выдвинуть более конкретное исключение.

class NotFromExcelError(Exception):
    pass

И в конце caller:

raise NotFromExcelError('Book.caller() must not be called directly. Call through Excel '
                        'or set a mock caller first with Book.set_mock_caller().')

Я надеюсь, что такой запрос на извлечение будет принят, потому что повышение голого Exception, как это происходит в настоящее время, выглядит действительно неправильно.

...