当我的脚本同时更新一个excel如果我要手动执行任何其他工作而另一个excel错误发生我正在使用dispatch
from win32com.client import Dispatch
excel = Dispatch('Excel.Application')
excel.Visible = True
file_name="file_name.xls"
workbook = excel.Workbooks.Open(file_name)
workBook = excel.ActiveWorkbook
sheet=workbook.Sheets(sheetno)
我正在犯这样的错误 (,com_error(-2147418111,'呼叫被被叫方拒绝',无,无)
有没有办法克服它..我可以更新另一个excel而不会发生错误..
答案 0 :(得分:5)
发生此错误是因为您正在调用的COM对象将拒绝外部调用,如果它已经处理了另一个操作。没有异步处理调用,行为似乎是随机的。
根据操作,您将看到pythoncom.com_error或pywintypes.com_error。一个简单的(如果不优雅)解决此问题的方法是使用try-except将调用包装到COM对象中,如果您遇到其中一个访问错误,请重试您的调用。
对于某些背景,请参阅Mark Hammond的chapter 12 excerpt from Python Programming on Win32的“错误处理”部分。安迪罗宾逊(O'Reilly 2000)。
在Siew Kam Onn's blog post "Python programming with Excel, how to overcome COM_error from the makepy generated python file"中还有一些关于Excel的有用信息。
答案 1 :(得分:1)
我最近遇到了同样的问题。虽然听起来可能有多个根本原因,但我的情况正在发生,因为Python过快地进行后续调用以便Excel跟上,特别是在外部查询刷新时。我解决了这种断断续续的问题"来电被拒绝了#34;错误是在我的大多数调用之间插入time.sleep()
并为任何特别冗长的调用(通常在7-15秒之间)增加sleep参数。这允许Excel在Python发出附加命令之前完成每个命令的时间。
答案 2 :(得分:0)
如果我没有启动另一个excel
,我的脚本会运行而不会出错我的问题是任何人都知道如何使用调度克服它 要么 是否还有其他任何用于python的excel模块,我可以处理这个问题吗?
excel= Dispatch('Excel.Application')
excel.Visible = True
file_name = "E:\Report.xls"
workbook = excel.Workbooks.Open(file_name)
sheet=workbook.Sheets(1)
# consider i am writing somethin in excel
sheet.Cells(1,1).Value = 'test1'
sheet.Cells(1,2).Value = 'test2'
sheet.Cells(1,3).Value = 'test3'
sheet.Cells(1,4).Value = 'test4'
sheet.Cells(1,5).Value = 'test5'
sheet.Cells(1,6).Value = 'test6'
sheet.Cells(1,7).Value = 'test7'
sheet.Cells(1,8).Value = 'test8'
答案 3 :(得分:0)
我一直在同一个问题上挣扎,但现在我已经提出了一种对我有效的解决方案。
我创建了一个类ComWrapper,用于包装Excel COM对象。它将自动包装每个嵌套对象并在ComWrapper中进行调用,并在将它们用作函数调用或对包装对象的赋值时对其进行拆包。包装器通过捕获“呼叫被被呼叫方拒绝”例外并重试呼叫直到达到顶部定义的超时来工作。如果超时,则最终将异常抛出到包装对象之外。
对包装对象的函数调用由_com_call_wrapper函数自动包装,这就是神奇的地方。
要使其工作,只需使用ComWrapper包装来自Dispatch的com对象,然后像在代码底部一样照常使用它。如有问题请发表评论。
import win32com.client
from pywintypes import com_error
import time
import logging
_DELAY = 0.05 # seconds
_TIMEOUT = 60.0 # seconds
def _com_call_wrapper(f, *args, **kwargs):
"""
COMWrapper support function.
Repeats calls when 'Call was rejected by callee.' exception occurs.
"""
# Unwrap inputs
args = [arg._wrapped_object if isinstance(arg, ComWrapper) else arg for arg in args]
kwargs = dict([(key, value._wrapped_object)
if isinstance(value, ComWrapper)
else (key, value)
for key, value in dict(kwargs).items()])
start_time = None
while True:
try:
result = f(*args, **kwargs)
except com_error as e:
if e.strerror == 'Call was rejected by callee.':
if start_time is None:
start_time = time.time()
logging.warning('Call was rejected by callee.')
elif time.time() - start_time >= _TIMEOUT:
raise
time.sleep(_DELAY)
continue
raise
break
if isinstance(result, win32com.client.CDispatch) or callable(result):
return ComWrapper(result)
return result
class ComWrapper(object):
"""
Class to wrap COM objects to repeat calls when 'Call was rejected by callee.' exception occurs.
"""
def __init__(self, wrapped_object):
assert isinstance(wrapped_object, win32com.client.CDispatch) or callable(wrapped_object)
self.__dict__['_wrapped_object'] = wrapped_object
def __getattr__(self, item):
return _com_call_wrapper(self._wrapped_object.__getattr__, item)
def __getitem__(self, item):
return _com_call_wrapper(self._wrapped_object.__getitem__, item)
def __setattr__(self, key, value):
_com_call_wrapper(self._wrapped_object.__setattr__, key, value)
def __setitem__(self, key, value):
_com_call_wrapper(self._wrapped_object.__setitem__, key, value)
def __call__(self, *args, **kwargs):
return _com_call_wrapper(self._wrapped_object.__call__, *args, **kwargs)
def __repr__(self):
return 'ComWrapper<{}>'.format(repr(self._wrapped_object))
_xl = win32com.client.dynamic.Dispatch('Excel.Application')
xl = ComWrapper(_xl)
# Do stuff with xl instead of _xl, and calls will be attempted until the timeout is
# reached if "Call was rejected by callee."-exceptions are thrown.
我在这里对一个较新的问题给出了相同的答案: https://stackoverflow.com/a/55892457/2828033