导入 pywinauto(或 comtypes)会破坏现有的 COM 对象
Importing pywinauto (or comtypes) clobbers existing COM object
使用 win32com.client.GetActiveObject
创建/获取 COM 对象,然后 import pywintypes
在每次调用原始 COM 对象时产生 AttributeError
。
重现代码
import win32com.client
catia_com = win32com.client.GetActiveObject('CATIA.Application')
# then later when needed, do some pywinauto stuff
import pywinauto.application
# back to working directly on catia com object
print(catia.caption) # raises Attribute error from within win32com.client
为什么会发生这种情况,如何解决?
我找到了一个解决方案,我想分享一下,但我也想听听关于我的理解的反馈,以及应该解决这个问题的适当依赖是什么,以防止其他人拥有同样的问题。
解决方案
在调用win32com.client
之前添加import comtypes
。
例子
import comtypes
import win32com.client
catia_com = win32com.client.GetActiveObject('CATIA.Application')
# then later when needed, do some pywinauto stuff
import pywinauto.application
# back to working directly on catia com object
print(catia.caption) # it works!
原因和解释(尽我所能确定)
TLDR
import comtypes
使用标志 COINIT_MULTITHREADED
调用 CoInitializeEx
,这恰好覆盖了 win32com.client.GetActiveObject
设置的模式。
完整解释
我得出这个结论是因为在 pywinauto.__init__
中注释掉 pythoncom.CoUninitialize()
(我担心它会杀死从 win32com.client.GetActiveObject
返回的 COM 对象)并重新运行以下代码错误来自 comtypes.__init__
:
OSError: [WinError -2147417850] Cannot change thread mode after it is set
我知道 comtypes.__init__
handels 选择了 CoInitializeEx
的默认标志并且无法推断出 win32com
库是怎样的,但我认为它也可能正在检查现有标志,所以我添加了 import comtypes
.
我还不清楚的地方
- 如何确定 win32com 的并发模型标志是什么?
- 调用win32com.client.GetActiveObject时如何指定并发模型标志?
- 为什么解决方案有效...在调用 win32com.client.GetActiveObject 之前调用
pythoncom.CoInitializeEx(0x0)
不起作用!
如果我能得到上面的答案,我可以建议 win32com 设置 sys.coinit_flags
(这是 comtypes.__init__
正在检查的地方)。
资源
使用 win32com.client.GetActiveObject
创建/获取 COM 对象,然后 import pywintypes
在每次调用原始 COM 对象时产生 AttributeError
。
重现代码
import win32com.client
catia_com = win32com.client.GetActiveObject('CATIA.Application')
# then later when needed, do some pywinauto stuff
import pywinauto.application
# back to working directly on catia com object
print(catia.caption) # raises Attribute error from within win32com.client
为什么会发生这种情况,如何解决?
我找到了一个解决方案,我想分享一下,但我也想听听关于我的理解的反馈,以及应该解决这个问题的适当依赖是什么,以防止其他人拥有同样的问题。
解决方案
在调用win32com.client
之前添加import comtypes
。
例子
import comtypes
import win32com.client
catia_com = win32com.client.GetActiveObject('CATIA.Application')
# then later when needed, do some pywinauto stuff
import pywinauto.application
# back to working directly on catia com object
print(catia.caption) # it works!
原因和解释(尽我所能确定)
TLDR
import comtypes
使用标志 COINIT_MULTITHREADED
调用 CoInitializeEx
,这恰好覆盖了 win32com.client.GetActiveObject
设置的模式。
完整解释
我得出这个结论是因为在 pywinauto.__init__
中注释掉 pythoncom.CoUninitialize()
(我担心它会杀死从 win32com.client.GetActiveObject
返回的 COM 对象)并重新运行以下代码错误来自 comtypes.__init__
:
OSError: [WinError -2147417850] Cannot change thread mode after it is set
我知道 comtypes.__init__
handels 选择了 CoInitializeEx
的默认标志并且无法推断出 win32com
库是怎样的,但我认为它也可能正在检查现有标志,所以我添加了 import comtypes
.
我还不清楚的地方
- 如何确定 win32com 的并发模型标志是什么?
- 调用win32com.client.GetActiveObject时如何指定并发模型标志?
- 为什么解决方案有效...在调用 win32com.client.GetActiveObject 之前调用
pythoncom.CoInitializeEx(0x0)
不起作用!
如果我能得到上面的答案,我可以建议 win32com 设置 sys.coinit_flags
(这是 comtypes.__init__
正在检查的地方)。