我有一个使用Python 2.7.9在Debian 8.1上运行Django 1.8.x的网站。该网站或机器不会负载过重。
网站使用“drive / v2”和“admin / directory_v1”(servicename / version)进行一些API调用。网站通常会调用files.insert,files.patch,files.move_to_trash或members.list
在过去的5-6个月里,所有人都没有问题。注意:Google于去年12月发布了“drive / v3”。大约一周前就出现了问题。
首先,我在某些(任何)API调用上遇到了一些偶发的SSL超时错误。然后我开始得到越来越多的错误。在某一点似乎是持久的,即一旦一个呼叫出现问题,那么它就会发生所有呼叫的任何呼叫。似乎没有涉及“files.move_to_trash”,除了一些零星的。
最近没有对我的网站进行任何修改。
我尝试更新“google-api-python-client”库
pip install --upgrade google-api-python-client
没有任何改进。
在接下来的几天里,我注意到持续性错误持续了几个小时,然后突然停止,所有事情都开始再次运行,几乎没有偶发错误,然后再次出现持续错误。间歇性操作。
在另一台我只用于“演示”的机器中,我得到了一些我以前从未遇到过的零星错误。
我认为非常重要的事情:我在进行API调用时会立即收到超时错误。这是一个真正的超时是很奇怪的。
我尝试的另一件事是从谷歌开发者控制台再次下载凭据JSON文件:我注意到文件中添加了一个新的密钥“project_id”(谷歌做了一些事情),无论如何都没有改变。我还试图从零重新创建凭据,重新加载JSON文件,取消关联并重新关联应用程序到谷歌驱动器,仍然没有成功。
根据谷歌支持的建议,我还检查了帐户安全设置中的“允许安全性较低的应用”已关闭。
这里有一个追溯样本:
'Traceback (most recent call last):
File ".\my_gdrive\\utils\\gdrive.py", line 130, in insert
filee = self.GDService.service.files().insert(body = body,media_body = media_body).execute()
File "/usr/local/lib/python2.7/dist-packages/oauth2client/util.py", line 140, in positional_wrapper
return wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/googleapiclient/http.py", line 694, in execute
_, body = self.next_chunk(http=http, num_retries=num_retries)
File "/usr/local/lib/python2.7/dist-packages/oauth2client/util.py", line 140, in positional_wrapper
return wrapped(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/googleapiclient/http.py", line 873, in next_chunk
headers=headers)
File "/usr/local/lib/python2.7/dist-packages/oauth2client/client.py", line 596, in new_request
redirections, connection_type)
File "/usr/local/lib/python2.7/dist-packages/httplib2/__init__.py", line 1609, in request
(response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
File "/usr/local/lib/python2.7/dist-packages/httplib2/__init__.py", line 1351, in _request
(response, content) = self._conn_request(conn, request_uri, method, body, headers)
File "/usr/local/lib/python2.7/dist-packages/httplib2/__init__.py", line 1307, in _conn_request
response = conn.getresponse()
File "/usr/lib/python2.7/httplib.py", line 1073, in getresponse
response.begin()
File "/usr/lib/python2.7/httplib.py", line 415, in begin
version, status, reason = self._read_status()
File "/usr/lib/python2.7/httplib.py", line 371, in _read_status
line = self.fp.readline(_MAXLINE + 1)
File "/usr/lib/python2.7/socket.py", line 476, in readline
data = self._sock.recv(self._rbufsize)
File "/usr/lib/python2.7/ssl.py", line 714, in recv
return self.read(buflen)
File "/usr/lib/python2.7/ssl.py", line 608, in read
v = self._sslobj.read(len or 1024)
SSLError: (\'The read operation timed out\',)
更新:添加了示例代码
from oauth2client.django_orm import CredentialsField
class CredentialsModel(models.Model):
id = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True)
credential = CredentialsField()
登录后,我会通过名为“gpermission”的视图调用una tantum来询问并向已记录的(系统)用户授予NA_GDRIVE_SCOPES权限。然后每隔几分钟就可以看到下面“THE CODE”部分中的代码。
NA_GDRIVE_SCOPES = ['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/admin.directory.group.member']
from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from oauth2client import xsrfutil
from oauth2client.client import flow_from_clientsecrets
from oauth2client.django_orm import Storage
from na_gdrive.models import CredentialsModel
def gdrive_get_credentials(func):
def decorator(request, *args, **kwargs):
storage = Storage(CredentialsModel, 'id', request.user, 'credential')
credential = storage.get()
if credential is None or credential.invalid:
# settings.NA_GDRIVE_CLIENT_SECRETS_PATH, name of a file containing the OAuth 2.0 information for this
# application, including client_id and client_secret, which are found
# on the API Access tab on the Google APIs
# Console <http://code.google.com/apis/console>
FLOW = flow_from_clientsecrets(settings.NA_GDRIVE_CLIENT_SECRETS_PATH,
scope = settings.NA_GDRIVE_SCOPES,
redirect_uri = urlparse.urljoin(settings.DOMAIN_ONLINE, reverse("gdrive_auth_return")))
FLOW.params['access_type'] = 'offline'
FLOW.params['approval_prompt'] = 'force'
FLOW.params['state'] = xsrfutil.generate_token(settings.SECRET_KEY, request.user) + defs.NA_GDRIVE_AUTHNEXT_SEP + request.GET.get("next", reverse("index"))
authorize_url = FLOW.step1_get_authorize_url()
return HttpResponseRedirect(authorize_url)
return func(request, storage, credential, *args, **kwargs)
return decorator
######## THE VIEWS ########
@login_required
def auth_return(request): #mapped on reverse("gdrive_auth_return")
if not xsrfutil.validate_token(settings.SECRET_KEY,
str(request.GET['state'].split(defs.NA_GDRIVE_AUTHNEXT_SEP)[0]), #http://stackoverflow.com/questions/27441567/django-1-7-google-oauth2-token-validation-failure
request.user):
return HttpResponseBadRequest()
FLOW = flow_from_clientsecrets(settings.NA_GDRIVE_CLIENT_SECRETS_PATH,
scope = settings.NA_GDRIVE_SCOPES,
redirect_uri = urlparse.urljoin(settings.DOMINIO_ONLINE, reverse("gdrive_auth_return")))
FLOW.params['access_type'] = 'offline'
FLOW.params['approval_prompt'] = 'force' #Questa non dovrebbe essere necessaria ma al momento è così che sta funzionando in primaindustria dopo i grossi problemi avuti con google
credential = FLOW.step2_exchange(request.REQUEST)
storage = Storage(CredentialsModel, 'id', request.user, 'credential')
storage.put(credential)
r_uri = request.GET['state'].split(defs.NA_GDRIVE_AUTHNEXT_SEP)[1]
return HttpResponseRedirect(r_uri)
#The view I call una tantum to ask/grant permission the first time
#when logged with User.objects.get(email = defs.GDRIVE_SYSTEMUSER_EMAIL)
@login_required
@gdrive_get_credentials
def gpermission(request, storage, credential):
return HttpResponse("Permissions granted")
######## THE CODE ########
from apiclient.discovery import build
from apiclient import errors
from apiclient import http
user = User.objects.get(email = defs.GDRIVE_SYSTEMUSER_EMAIL)
storage = Storage(CredentialsModel, 'id', user, 'credential')
credential = storage.get()
if credential is None or credential.invalid is True:
raise Exception, 'Bad GDrive credentials'
httpobj = credential.authorize(httplib2.Http())
service = build("drive", "v2", http = httpobj)
media_body = MediaFileUpload(filename, mimetype = mime_type, resumable = True)
body = {
'title': title,
'description': description,
'mimeType': mime_type,
'parents' : parents_id
}
try:
filee = service.files().insert(body = body, media_body = media_body).execute() #This gets time SSL Timeout Error
return filee
except errors.HttpError, error:
print 'An error occured: %s' % error
raise
更新:添加额外信息
在最后几天,我打开了一个python shell,在那里我用storage.get()读取了凭证对象(只有一次)。如果我在获取持久性错误时从shell(仍然打开)将文件提交到谷歌驱动器上,我没有任何问题。