2017-08-28 94 views
0

我目前正在制作一个连接到Google电子表格(gspread)的Discord-bot。 但我运行一段时间后,它开始发出错误,它不能连接到我的gspread了(除非我重新启动它)。Python - Gspread请求错误401

是我收到的错误:(https://hastebin.com/odutucawuv.tex

Ignoring exception in command sub 
Traceback (most recent call last): 
File "C:\Python36\lib\site-packages\discord.py-0.16.10- 
py3.6.egg\discord\ext\commands\core.py", line 50, in wrapped 
ret = yield from coro(*args, **kwargs) 
File "C:\Users\simvid-5\Desktop\Pogomoves\DiscordBot.py", line 65, in sub 
val = worksheet.cell(cell_name.row, cell_name.col+4) 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\models.py", line 392, in cell 
self._cell_addr(row, col)) 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\client.py", line 210, in get_cells_cell_id_feed 
r = self.session.get(url) 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\httpsession.py", line 73, in get 
return self.request('GET', url, params=params, **kwargs) 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\httpsession.py", line 69, in request 
response.status_code, response.content)) 
gspread.exceptions.RequestError: (401, '401: 
b\'<HTML>\\n<HEAD>\\n<TITLE>Unauthorized</TITLE>\\n</HEAD>\\n<BODY 
BGCOLOR="#FFFFFF" TEXT="#000000">\\n<H1>Unauthorized</H1>\\n<H2>Error 
401</H2>\\n</BODY>\\n</HTML>\\n\'') 

The above exception was the direct cause of the following exception: 

Traceback (most recent call last): 
File "C:\Python36\lib\site-packages\discord.py-0.16.10- 
py3.6.egg\discord\ext\commands\bot.py", line 846, in process_commands 
yield from command.invoke(ctx) 
File "C:\Python36\lib\site-packages\discord.py-0.16.10- 
py3.6.egg\discord\ext\commands\core.py", line 374, in invoke 
yield from injected(*ctx.args, **ctx.kwargs) 
File "C:\Python36\lib\site-packages\discord.py-0.16.10- 
py3.6.egg\discord\ext\commands\core.py", line 54, in wrapped 
raise CommandInvokeError(e) from e 
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: 
RequestError: (401, '401: 
b\'<HTML>\\n<HEAD>\\n<TITLE>Unauthorized</TITLE>\\n</HEAD>\\n<BODY 
BGCOLOR="#FFFFFF" TEXT="#000000">\\n<H1>Unauthorized</H1>\\n<H2>Error 
401</H2>\\n</BODY>\\n</HTML>\\n\'') 
Ignoring exception in command add 
Traceback (most recent call last): 
File "C:\Users\simvid-5\Desktop\Pogomoves\DiscordBot.py", line 130, in add 
cell_name = worksheet.find(str(member)) 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\models.py", line 711, in find 
return self._finder(finditem, query) 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\models.py", line 696, in _finder 
cells = self._fetch_cells() 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\models.py", line 331, in _fetch_cells 
feed = self.client.get_cells_feed(self) 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\client.py", line 176, in get_cells_feed 
r = self.session.get(url) 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\httpsession.py", line 73, in get 
return self.request('GET', url, params=params, **kwargs) 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\httpsession.py", line 69, in request 
response.status_code, response.content)) 
gspread.exceptions.RequestError: (401, '401: 
b\'<HTML>\\n<HEAD>\\n<TITLE>Unauthorized</TITLE>\\n</HEAD>\\n<BODY 
BGCOLOR="#FFFFFF" TEXT="#000000">\\n<H1>Unauthorized</H1>\\n<H2>Error 
401</H2>\\n</BODY>\\n</HTML>\\n\'') 

During handling of the above exception, another exception occurred: 

Traceback (most recent call last): 
File "C:\Python36\lib\site-packages\discord.py-0.16.10- 
py3.6.egg\discord\ext\commands\core.py", line 50, in wrapped 
ret = yield from coro(*args, **kwargs) 
File "C:\Users\simvid-5\Desktop\Pogomoves\DiscordBot.py", line 136, in add 
cell_list = worksheet.range('A2:A100') 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\models.py", line 72, in wrapper 
return method(self, *args, **kwargs) 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\models.py", line 412, in range 
params={'range': name, 'return-empty': 'true'} 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\client.py", line 176, in get_cells_feed 
r = self.session.get(url) 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\httpsession.py", line 73, in get 
return self.request('GET', url, params=params, **kwargs) 
File "C:\Python36\lib\site-packages\gspread-0.6.2- 
py3.6.egg\gspread\httpsession.py", line 69, in request 
response.status_code, response.content)) 
gspread.exceptions.RequestError: (401, '401: 
b\'<HTML>\\n<HEAD>\\n<TITLE>Unauthorized</TITLE>\\n</HEAD>\\n<BODY 
BGCOLOR="#FFFFFF" TEXT="#000000">\\n<H1>Unauthorized</H1>\\n<H2>Error 
401</H2>\\n</BODY>\\n</HTML>\\n\'') 

The above exception was the direct cause of the following exception: 

Traceback (most recent call last): 
File "C:\Python36\lib\site-packages\discord.py-0.16.10- 
py3.6.egg\discord\ext\commands\bot.py", line 846, in process_commands 
yield from command.invoke(ctx) 
File "C:\Python36\lib\site-packages\discord.py-0.16.10- 
py3.6.egg\discord\ext\commands\core.py", line 374, in invoke 
yield from injected(*ctx.args, **ctx.kwargs) 
File "C:\Python36\lib\site-packages\discord.py-0.16.10- 
py3.6.egg\discord\ext\commands\core.py", line 54, in wrapped 
raise CommandInvokeError(e) from e 
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: 
RequestError: (401, '401: 
b\'<HTML>\\n<HEAD>\\n<TITLE>Unauthorized</TITLE>\\n</HEAD>\\n<BODY 
BGCOLOR="#FFFFFF" TEXT="#000000">\\n<H1>Unauthorized</H1>\\n<H2>Error 
401</H2>\\n</BODY>\\n</HTML>\\n\'') 

和我使用,如果是任何人的帮助,了解上述问题的一个功能,我可以提供更多的我的代码如果有必要修复它:

import discord 
import asyncio 
import random 
import pickle 
import os 
import gspread 
import time 

from oauth2client.service_account import ServiceAccountCredentials 
from discord.ext import commands 

prefix = '!' 

def returnPrefix(): 
    global prefix 
    return prefix 

bot = commands.Bot(returnPrefix()) 

scope = ['https://spreadsheets.google.com/feeds'] 
credentials = 
ServiceAccountCredentials.from_json_keyfile_name('GoogleSpreadsheetCreds.json', scope) 
gc = gspread.authorize(credentials) 
sh = gc.open("MyWorksheet") 
worksheet = sh.sheet1 


@bot.event 
async def on_ready(): 
     print('Logged in as') 
     print(bot.user.name) 
     print(bot.user.id) 
     print('-----') 
     await bot.change_presence(game=discord.Game(name='Stackoverflow')) 



@bot.command(pass_context=True) 
@commands.has_role("Premium") 
async def sub(ctx, member: discord.Member = None): 
    global cell_name 
    if member is None: 
     member = ctx.message.author 

    #Delete user_command. 
    await bot.delete_message(ctx.message) 

    #Retrieve user from commander. 
    Username = '{0}'.format(member) 

    try: 
     #Try to find the username in spreadsheet. 
     cell_name = worksheet.find(Username) 
    except: #If we dont find the username. 
     await bot.say("Your name ("+Username+") was not found, please contact someone for help.") 

    if cell_name.value == Username: #If we find the username. 
     #Retrieve some values. 
     val = worksheet.cell(cell_name.row, cell_name.col+4) 
     val_date = worksheet.cell(cell_name.row, cell_name.col+3) 
     remaining_days = val.value 
     remaining_date = val_date.value 

     #Send a message to a member. 
     await bot.send_message(member, 
          "```Username: "+ Username+ 
          "\nRemaining days: "+remaining_days+ 
          "\nDate for expiration: "+remaining_date+"```") 

回答

1

您的访问令牌在一段时间后过期。从OAuth 2.0 docs

  1. 刷新访问令牌,如有必要。

访问令牌的生命周期有限。如果您的应用程序需要在单个访问令牌的生命周期之外访问Google API,则可以获取刷新令牌。刷新令牌允许您的应用程序获取新的访问令牌。

注意:将刷新令牌保存在安全的长期存储中,只要它们保持有效,就继续使用它们。限制适用于每个客户端 - 用户组合以及每个用户在所有客户端上发布的刷新令牌的数量,这些限制是不同的。如果您的应用程序请求足够的刷新令牌来超过其中一个限制,旧的刷新令牌将停止工作。

我不认为gspread配备了处理刷新标记。您可能只需要抓住此异常并根据需要重新进行验证。

编辑:

gspread源后,我想你可能能够通过简单地调用刷新令牌gc.login()

编辑:

issuegspread一对夫妇申请几年前,但它没有明显的原因关闭。这里是one approach来解决它:

def add_row(row): 
    try: 
     gs_client = gspread.authorize(creds) 
     gs_worksheet = gs_client.open("foo").sheet1 
     if creds.access_token_expired: 
      gs_client.login() # refreshes the token 
     gs_worksheet.append_row(row) 
    except Exception, e: 
     traceback.print_exc() 

但我认为这是矫枉过正。你应该能够你try:块之前只是调用gc.login()权:

gc.login() 
try: 
    #Try to find the username in spreadsheet. 
    cell_name = worksheet.find(Username) 
except: #If we dont find the username. 
+0

谢谢,我会尝试!所以gc.login()不需要输入? – Simvid

+0

没错,没有参数。您需要在访问令牌过期后调用它。 – Jeff

+0

谢谢,这工作! – Simvid

0

这里唯一合理的罪魁祸首是您的帐户凭据。尝试在Google Developer Console上创建新的凭据并使用它。

+0

尝试,这也!谢谢 – Simvid