gpt4 book ai didi

python - 使用 pythoncom 在 Python 进程之间编码(marshal) COM 对象

转载 作者:行者123 更新时间:2023-11-28 22:50:12 27 4
gpt4 key购买 nike

我希望有人能帮助我从 Python 对 Excel 进行编码跨进程调用。

我有一个通过 Python 启动的 Excel session ,我知道它会在需要从单独的 Python 进程访问时启动并运行。使用来自 pythoncom 模块的 CoMarshalInterfaceInStream()CoGetInterfaceAndReleaseStream() 调用编码,我已经按照需要进行了所有工作,但我需要重复访问流(我只能在我的例子中设置一次),并且 CoGetInterfaceAndReleaseStream() 允许对接口(interface)进行一次访问。

我相信我想要实现的目标可以通过 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() 时出现此错误(我想这与第三个参数有关):

"ValueError: argument is not a COM object (got type=instance)"

有谁知道我怎样才能让这个简单的例子起作用?

提前致谢

最佳答案

在经历了很多焦虑之后,我设法解决了我面临的问题,实际上我也会描述后续的问题。

首先,我猜对了我最初的问题是调用 pythoncom.CoMarshalInterface() 时的第三个参数。事实上,我应该引用我的 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()

我希望这能帮助其他人克服我所面临的障碍!

关于python - 使用 pythoncom 在 Python 进程之间编码(marshal) COM 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22863646/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com