【问题标题】:Decorate each method of win32com COM object [duplicate]装饰win32com COM对象的每个方法[重复]
【发布时间】:2017-01-24 07:05:36
【问题描述】:

Python 3
我通过 win32com.client.Dispatch 有一个 COM 对象,其中包含许多用于自动化应用程序的方法。我希望每次调用 COM 对象的任何方法时,python 都会根据返回的值(实际上是日志记录)执行某些操作。
我的自动化伪代码是这样的:

obj = win32com.client.DispatchEx("3rdParty.Application")
obj.methodA(Parameter)
obj.methodB()
obj.non_method_call
obj.methodN()
...

当对 obj 进行任何方法调用时,我希望这个伪代码的意图发生:

x = obj.any_method(*args)
if x:
    logger.debug(any_method.__name__ + ' was called at ' + datetime.now().strftime("%H:%M") + ' with parameters ' + str(*args)
else:
    logger.error(obj.cerrmsg)
    obj.logout

请注意,any_method.__name__ 部分会很好,但并不重要。 python 可以做到这一点,尤其是使用 COM 对象,并且无需为有限的一组方法编写逻辑吗?
装饰器听起来是对的,因为它们修改了函数/类,但是我审查过的帖子在这种情况下不起作用(比如通过对象的方法字典),然后我听说它们只适用于我自己的代码中定义的方法。有人建议使用@Property,但我不知道在这种情况下如何应用它。
欢迎使用高级技巧(getattr、元类、functools、wraps 等),但请演示一下。

【问题讨论】:

  • 通过构建 TessellatingHeckler 的响应,我设法获得了一个可行的解决方案。
  • class COM_Wrapper(object): def __init__(self, COM_Class_String): self.__dict__['objCOM'] = win32com.client.DispatchEx(COM_Class_String) def __getattr__(self, name): if hasattr(self, 'objCOM'): if hasattr(self.objCOM, name): return self.objCOM.__getattr__(name) else: raise AttributeError("not in class nor COM Object") else: return None '__getattr__` 允许我的班级拥有自己的方法。 (避免名称冲突!)'_FlagAsMethod` & __AttrToID__ 是其他有用的 python COM 方法

标签: python python-3.x properties win32com python-decorators


【解决方案1】:

我测试了我在评论中提到的方法,针对 win32com.client 并遇到了一个基本问题:

self.__getattribute__ 的递归性质意味着尝试存储对象然后使用self.stored_obj 会失败,因为它会永远递归调用__getattribute__

如果您原谅将全局变量作为一种骇人听闻的方式来解决这个问题,并且意味着您一次只能使用一次,那么它基本上可以工作。

即调试/跟踪您的 COM 对象发生的事情可能没问题,但这不是一个好的或强大的解决方案:

global _wrapped_object

class LogWrap:
    def __init__(self, object):
        global _wrapped_object
        _wrapped_object = object

    def __getattribute__(self, name):
        global _wrapped_object

        next_hop_attr = _wrapped_object.__getattr__(name)

        if callable(next_hop_attr):

            def logging_attr(*args, **kwargs):
                retval = next_hop_attr(*args, **kwargs)
                print("logging a call to {0} with args -{1}-".format(name, ','.join(args)))
                print("Returned: {0}".format(retval))
                return retval

            return logging_attr

        else:
            return next_hop_attr

    def __setattr__(self, name, value):
        global _wrapped_object
        _wrapped_object.__setattr__(name, value)


from win32com.client import Dispatch
ie = Dispatch('InternetExplorer.Application')
ie = LogWrap(ie)
ie.Visible = True

ie.Navigate2('google.com')

带有示例输出:

>>> logging a call to Navigate2 with args -google.com-
Returned: None
>>> 

【讨论】:

  • 谢谢,这有效并解决了我的问题!如果有更“pythonic”的方式来做到这一点,我很乐意看到它,或者避免使用全局变量。
猜你喜欢
  • 2020-08-12
  • 1970-01-01
  • 2012-02-09
  • 1970-01-01
  • 2016-08-14
  • 1970-01-01
  • 2015-03-07
  • 2021-06-24
  • 1970-01-01
相关资源
最近更新 更多