[英]difference between pywintypes and pythoncom for com_error
[英]Marshaling COM objects between Python processes using pythoncom
我希望有人可以帮助我能够从Python中对Excel进行封送的跨进程调用。
我有一个通过Python启动的Excel会话,我知道它将在需要从单独的Python进程访问时启动并运行。 我通过使用来自pythoncom模块的CoMarshalInterfaceInStream()
和CoGetInterfaceAndReleaseStream()
调用来完成所有工作,但我需要重复访问流(我只能在我的情况下设置一次),并且CoGetInterfaceAndReleaseStream()
允许一次 - 只能访问界面。
我相信我想要实现的目标可以通过CreateStreamOnHGlobal()
, CoMarshalInterface()
和CoUnmarshalInterface()
但是我无法使它工作,几乎可以肯定,因为我没有传递正确的参数。
我没有详细描述我的主要场景,而是设置了一个简单的示例程序,如下所示 - 显然这是在同一个过程中进行的,但一次只能进行一步! 以下代码段正常:
import win32com.client
import pythoncom
excelApp = win32com.client.DispatchEx("Excel.Application")
marshalledExcelApp = pythoncom.CoMarshalInterThreadInterfaceInStream(pythoncom.IID_IDispatch, excelApp)
xlApp = win32com.client.Dispatch(
pythoncom.CoGetInterfaceAndReleaseStream(marshalledExcelApp, pythoncom.IID_IDispatch))
xlWb = xlApp.Workbooks.Add()
xlWs = xlWb.Worksheets.Add()
xlWs.Range("A1").Value = "AAA"
但是,当我尝试以下内容时:
import win32com.client
import pythoncom
excelApp = win32com.client.DispatchEx("Excel.Application")
myStream = pythoncom.CreateStreamOnHGlobal()
pythoncom.CoMarshalInterface(myStream,
pythoncom.IID_IDispatch,
excelApp,
pythoncom.MSHCTX_LOCAL,
pythoncom.MSHLFLAGS_TABLESTRONG)
myUnmarshaledInterface = pythoncom.CoUnmarshalInterface(myStream, pythoncom.IID_IDispatch)
在调用pythoncom.CoMarshalInterface()
时,我得到了这个错误(我想这与第3个参数有关pythoncom.CoMarshalInterface()
:
"ValueError: argument is not a COM object (got type=instance)"
有谁知道我怎么能让这个简单的例子起作用?
提前致谢
经过深深的焦虑,我已经设法解决了我所面临的问题,以及随后我将要描述的问题。
首先,我猜测我的初始问题是调用pythoncom.CoMarshalInterface()时的第3个参数是正确的。 实际上,我应该一直在引用我的excelApp变量的oleobj属性:
pythoncom.CoMarshalInterface(myStream,
pythoncom.IID_IDispatch,
excelApp._oleobj_,
pythoncom.MSHCTX_LOCAL,
pythoncom.MSHLFLAGS_TABLESTRONG)
但是,我接着遇到了一个不同的错误消息,这次调用pythoncom.CoUnmarshalInterface():
com_error: (-2147287010, 'A disk error occurred during a read operation.', None, None)
事实证明,这是因为在使用之前需要使用Seek()方法重置流指针:
myStream.Seek(0,0)
最后,尽管大多数方面都正常工作,但我发现尽管在编组的Excel对象上使用Quit()并在代码结束之前将所有变量显式设置为None,但我还是留下了一个僵尸Excel进程。 尽管事实上pythoncom._GetInterfaceCount()返回0。
事实证明,我必须通过调用CoReleaseMarshalData()显式清空我创建的流(首先重新重置流指针)。 因此,整个示例代码段如下所示:
import win32com.client
import pythoncom
pythoncom.CoInitialize()
excelApp = win32com.client.DispatchEx("Excel.Application")
myStream = pythoncom.CreateStreamOnHGlobal()
pythoncom.CoMarshalInterface(myStream,
pythoncom.IID_IDispatch,
excelApp._oleobj_,
pythoncom.MSHCTX_LOCAL,
pythoncom.MSHLFLAGS_TABLESTRONG)
excelApp = None
myStream.Seek(0,0)
myUnmarshaledInterface = pythoncom.CoUnmarshalInterface(myStream, pythoncom.IID_IDispatch)
unmarshalledExcelApp = win32com.client.Dispatch(myUnmarshaledInterface)
# Do some stuff in Excel in order to prove that marshalling has worked.
unmarshalledExcelApp.Visible = True
xlWbs = unmarshalledExcelApp.Workbooks
xlWb = xlWbs.Add()
xlWss = xlWb.Worksheets
xlWs = xlWss.Add()
xlRange = xlWs.Range("A1")
xlRange.Value = "AAA"
unmarshalledExcelApp.Quit()
# Clear the stream now that we have finished
myStream.Seek(0,0)
pythoncom.CoReleaseMarshalData(myStream)
xlRange = None
xlWs = None
xlWss = None
xlWb = None
xlWbs = None
myUnmarshaledInterface = None
unmarshalledExcelApp = None
myStream = None
pythoncom.CoUninitialize()
我希望这能帮助其他人克服我遇到的障碍!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.