问题描述
我使用 Python Gmail API 的程序遇到了很多 socket.timeout 错误。我经常收到以下信息:
socket.timeout: The read operation timed out
此错误似乎是随机的,通常出现在任何 Gmail API 函数中。我尝试修改套接字超时参数。但是,更改此参数似乎并没有消除问题。我已经将它从 1 秒、10 秒和 600 秒变化了。
socket.setdefaulttimeout(10)
或者对于 httplib2.Http 对象:
def build_http(self):
"""Builds httplib2.Http object
Returns:
A httplib2.Http object,which is used to make http requests,and which has timeout set by default.
To override default timeout call
socket.setdefaulttimeout(timeout_in_sec)
before interacting with this method.
"""
try:
return httplib2.Http(timeout=10)
except:
self.GLogger.error("An error was encountered in build_http")
tb = traceback.format_exc()
self.GLogger.exception(tb)
return False
以下代码用于初始化 Gmail API 服务。
def gmailAPIInitialize(self):
try:
self.waitForInternet()
self.GLogger.info("Initializing the Gmail API Service")
creds = None
# The file token.pickle stores the user's access and refresh tokens,and is
# created automatically when the authorization flow completes for the first
# time.
if self.reprocess is True:
token_pickle_file = 'Gmail_token_2.pickle'
credentials_file = 'Gmail_credentials_2.json'
else:
token_pickle_file = 'Gmail_token_1.pickle'
credentials_file = 'Gmail_credentials_1.json'
if os.path.exists(token_pickle_file):
with open(token_pickle_file,'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available,let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
credentials_file,ScopES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open(token_pickle_file,'wb') as token:
pickle.dump(creds,token)
#service = build('gmail','v1',credentials=creds,cache_discovery=False)
service = build('gmail',cache_discovery=False)
self.gmailAPIService = service
self.GLogger.info("Successfully initialized the Gmail API Service")
return True
except:
self.GLogger.error("An error was encountered while attempting to initialize the Gmail API")
tb = traceback.format_exc()
self.GLogger.exception(tb)
return False
同样,几乎任何函数都会触发这个问题。但这里有一些例子:
主题列表:
def gmailAPIMessageLabelSearchThreads(self,labelList,userID="me",allPages=False,reverSEOrder=False):
try:
self.GLogger.info("Attempting to search email threads with labelList (" + str(labelList)+ ") and userID (" +str(userID)+ ")")
service = self.gmailAPIService
if service is None:
logging.error('Gmail Service not initialized')
return False
response = service.users().threads().list(userId=userID,labelIds=labelList,maxResults=500,fields="threads(id),nextPagetoken").execute()
messages = []
if 'messages' in response:
messages.extend(response['messages'])
if (allPages is True):
while 'nextPagetoken' in response:
page_token = response['nextPagetoken']
response = service.users().messages().list(userId=userID,pagetoken=page_token,nextPagetoken").execute()
if 'messages' in response:
messages.extend(response['messages'])
if reverSEOrder is True:
messages.reverse()
self.GLogger.info("Successfully searched emails with labelList (" + str(labelList)+ ") and userID (" +str(userID)+ "). Number of matching emails (" +str(len(messages))+ ")")
return messages
except:
self.GLogger.error("An error was encounrtered while searching for messages with Google Api and label list")
tb = traceback.format_exc()
self.GLogger.exception(tb)
return False
发送电子邮件:
def gmailAPISendEmail(self,message,userID="me"):
try:
service = self.gmailAPIService
self.GLogger.info("Attempting to send email message")
response = (service.users().messages().send(userId=userID,body=message).execute())
responseID = str(response['id'])
self.GLogger.info("Successfully sent email message with ID (" + responseID +")")
return responseID
except:
self.GLogger.error("Failed to send email message")
tb = traceback.format_exc()
self.GLogger.exception(tb)
return False
消息列表:
def gmailAPIMessageLabelSearch(self,reverSEOrder=False,numPages=None):
try:
self.GLogger.info("Attempting to search emails with labelList (" + str(labelList)+ ") and userID (" +str(userID)+ ")")
service = self.gmailAPIService
if service is None:
logging.error('Gmail Service not initialized')
return False
#response = service.users().messages().list(userId=userID,fields='messages(id)').execute()
response = service.users().messages().list(userId=userID,fields="messages(id),nextPagetoken").execute()
messages = []
if 'messages' in response:
messages.extend(response['messages'])
numPages_Processed = 0
if (allPages is True):
while 'nextPagetoken' in response:
page_token = response['nextPagetoken']
#response = service.users().messages().list(userId=userID,fields='messages(id)',maxResults=500).execute()
response = service.users().messages().list(userId=userID,nextPagetoken").execute()
if 'messages' in response:
messages.extend(response['messages'])
numPages_Processed = numPages_Processed + 1
if (numPages is not None) and numPages_Processed>=numPages:
break
if reverSEOrder is True:
messages.reverse()
self.GLogger.info("Successfully searched emails with labelList (" + str(labelList)+ ") and userID (" +str(userID)+ "). Number of matching emails (" +str(len(messages))+ ")")
listToReturn = list()
for message in messages:
listToReturn.append(message['id'])
return listToReturn
except:
self.GLogger.error("An error was encounrtered while searching for messages with Google Api and label list")
tb = traceback.format_exc()
self.GLogger.exception(tb)
return False
附件下载:
def gmailAPIDownloadAttachments(self,messageID,message=None,userID="me"):
try:
service = self.gmailAPIService
self.GLogger.info("Attempting to download attachments from messageID (" +str(messageID)+ ")")
if message is None:
message = self.gmailAPIGetFullMessage(messageID,userID=userID)
if message is False:
self.GLogger.error("Failed to extract message (" +str(messageID)+ ") for downloading attachments")
return False
attachmentList = list()
payload = message['payload']
if 'parts' in payload:
parts = payload['parts']
for part in parts:
if part['filename']:
if 'data' in part['body']:
data = part['body']['data']
else:
att_id = part['body']['attachmentId']
att = service.users().messages().attachments().get(userId=userID,messageId=messageID,id=att_id).execute()
data = att['data']
file_data = base64.urlsafe_b64decode(data.encode('UTF-8'))
filename = part['filename']
extSearch = filename.find('.')
if extSearch == -1:
ext = ""
partFileName = filename[0:extSearch]
else:
ext = filename[extSearch+1:]
partFileName = filename[0:extSearch]
theAttachment = Attachment(filename,partFileName,ext,file_data)
attachmentList.append(theAttachment)
self.GLogger.info("Successfully downloaded attachments from messageID (" +str(messageID)+ ")")
return(attachmentList)
except:
self.GLogger.error("Encountered an error while attempting to download email attacments from messageID (" +str(messageID)+ ")")
tb = traceback.format_exc()
self.GLogger.exception(tb)
return False
Batch Requests,其中 searchResultParts 是一个列表列表,其中每个嵌入的列表包含 100 个消息 ID:
for searchResultPart in searchResultParts:
batch = service.new_batch_HTTP_Request(callback=self.theEmailCallback)
for msgiD in searchResultPart: #Loop through each messageID
request1 = service.users().messages().get(userId=userID,id=msgiD)
batch.add(request=request1,request_id=msgiD)
batch.execute(http=self.http_toUse)
我使用了多个 Python Gmail API 函数,这些只是其中的一个子集。但是,所有这些都倾向于在某个时候产生 socket.timeout 错误。目前,我的防火墙已关闭(ufw 处于非活动状态)。
我相信我正在按预期使用这些功能,并且相信这个问题出在 Google 身上。是否有谷歌团队成员可以对此进行调查?我能做些什么来解决这个问题?这些 socket.timeout 错误经常发生,导致我的应用程序出现问题。
我的互联网连接是千兆光纤,用于上传和下载。
编辑** 我现在通过这个函数调用我所有的 Python Gmail API 请求。它将等待 50 毫秒(然后每次重试多 50 毫秒),然后重试直到请求成功或直到进行了 10 次重试。 socket.timeout 错误仍然很普遍,但根据我目前的观察,似乎大多数 socket.timeout 错误会在 2 或 3 次重试后发生。
def executeGmailAPI_withretry(self,request):
try:
response_valid = False
num_retries = 0
while num_retries < 10:
try:
response = request.execute()
response_valid = True
break
except socket.timeout:
num_retries = num_retries + 1
time.sleep(0.05*num_retries)
except:
self.GLogger.error("An error was encounrtered in executeGmailAPI_withretry")
tb = traceback.format_exc()
self.GLogger.exception(tb)
num_retries = num_retries + 1
time.sleep(0.05*num_retries)
if response_valid is False:
return False
else:
return response
except:
self.GLogger.error("An error was encounrtered in executeGmailAPI_withretry")
tb = traceback.format_exc()
self.GLogger.exception(tb)
return False
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)