我目前正在使用gspread在网络服务器上连续访问Google表格文档。
它托管在Flask网络服务器(Apache WSGI)上,因此与Google的连接必须是连续的,并且需要进行连续的身份验证。
我遇到一个问题,几个小时后,我需要重新生成书本对象(重新进行身份验证),否则我将遇到此问题(请参见下文)。
下面是我为解决问题所做的工作,但是我仍然遇到同样的问题,并且想知道您是否有任何想法。
有5到6个不同的工作表,我正在创建一个使用不同方法访问每个工作表的类(所有方法均继承自Access)。
book = authorise()
employee, shift, clock, client, payment = Employee(book), Shift(book),
Clock(book), Client(book), Payment(book)
def refresh_google_access(self): #CALLED EVERY 40 MINUTES
book = authorise()
employee._refresh(book)
shift._refresh(book)
clock._refresh(book)
client._refresh(book)
payment._refresh(book)
def authorise():
scope = ['https://spreadsheets.google.com/feeds']
credentials = ServiceAccountCredentials.from_json_keyfile_name('clocker/access.json', scope)
gc = gspread.authorize(credentials)
book = gc.open_by_key(SHEET_KEY)
return book
class Access:
def _refresh(self, book):
self.__init__(book)
class Employee(Access):
def __init__(self, book):
self.sheet = book.worksheet("Employee List")
...
class Clock(Access):
def __init__(self, book):
self.sheet = book.worksheet("Time Log")
...
class Shift(Access):
def __init__(self, book):
self.sheet = book.worksheet("Shift List")
...
class Client(Access):
def __init__(self, book):
self.sheet = book.worksheet("Client List")
...
class Payment(Access):
def __init__(self, book):
self.sheet = book.worksheet("Payments")
...
几个小时后(4-24小时之间的任何时间),我会收到此错误:
Traceback (most recent call last):
File "/home/ve/lib/python3.4/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/home/ve/lib/python3.4/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/ve/lib/python3.4/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/ve/lib/python3.4/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/ve/lib/python3.4/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/home/ve/lib/python3.4/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/var/www/clocker/clocker/routes.py", line 43, in voice
clocked_in = clock.is_clocked_in(id)
File "/var/www/clocker/clocker/sheet_access.py", line 115, in is_clocked_in
latest_clock_in = self.get_latest_clock_in(id)
File "/var/www/clocker/clocker/sheet_access.py", line 107, in get_latest_clock_in
result = self.sheet.findall(str(id))
File "/home/ve/lib/python3.4/site-packages/gspread/models.py", line 814, in findall
return list(self._finder(filter, query))
File "/home/ve/lib/python3.4/site-packages/gspread/models.py", line 779, in _finder
data = self.spreadsheet.values_get(self.title)
File "/home/ve/lib/python3.4/site-packages/gspread/models.py", line 110, in values_get
r = self.client.request('get', url, params=params)
File "/home/ve/lib/python3.4/site-packages/gspread/client.py", line 79, in request
raise APIError(response)
gspread.exceptions.APIError: {
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"status": "UNAUTHENTICATED"
}
}
几乎每次通过重新启动服务器即可解决此问题。
重新生成book对象似乎无法解决该问题,我已经检查了本书的id
每40分钟更改一次。
答案 0 :(得分:0)
如果我正确理解,在使用时,我会握住gc
并在需要数据时致电book = gc.open_by_key(SHEET_KEY)
。
基本上没有保存book
,而是保存gc
,而不是将using System; using System.IO; using System.Text;
// Using encoding from BOM or UTF8 if no BOM found,
// check if the file is valid, by reading all lines
// If decoding fails, use the local "ANSI" codepage
public string DetectFileEncoding(Stream fileStream)
{
var Utf8EncodingVerifier = Encoding.GetEncoding("utf-8", new EncoderExceptionFallback(), new DecoderExceptionFallback());
using (var reader = new StreamReader(fileStream, Utf8EncodingVerifier,
detectEncodingFromByteOrderMarks: true, leaveOpen: true, bufferSize: 1024))
{
string detectedEncoding;
try
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
}
detectedEncoding = reader.CurrentEncoding.BodyName;
}
catch (Exception e)
{
// Failed to decode the file using the BOM/UT8.
// Assume it's local ANSI
detectedEncoding = "ISO-8859-1";
}
// Rewind the stream
fileStream.Seek(0, SeekOrigin.Begin);
return detectedEncoding;
}
}
[Test]
public void Test1()
{
Stream fs = File.OpenRead(@".\TestData\TextFile_ansi.csv");
var detectedEncoding = DetectFileEncoding(fs);
using (var reader = new StreamReader(fs, Encoding.GetEncoding(detectedEncoding)))
{
// Consume your file
var line = reader.ReadLine();
...
保存为全局变量,这样您先前经过身份验证的会话将被保留并用于进一步的请求。