【问题标题】:Python - Gspread Request Error 401Python - Gspread 请求错误 401
【发布时间】:2018-02-05 10:46:28
【问题描述】:

我目前正在制作一个连接到 Google 电子表格 (gspread) 的 Discord-bot。 但是在我运行它一段时间后,它开始发出错误并且它无法再连接到我的 gspread(除非我重新启动它)。

我收到的错误:(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+"```")

【问题讨论】:

    标签: python python-3.x google-sheets gspread discord.py


    【解决方案1】:

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

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

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

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

    我不相信gspread 具备处理刷新令牌的能力。您可能只是能够捕获此异常并根据需要重新进行身份验证。

    编辑:

    查看gspread 源后,我认为您可能只需调用gc.login() 即可刷新您的令牌

    编辑:

    这个issue 是在几年前与gspread 一起提交的,但由于没有明显的原因而被关闭。这是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.
    

    【讨论】:

    • 谢谢,我会试试的!所以 gc.login() 不需要输入?
    • 对,没有参数。您需要在 访问令牌过期后调用它。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-12
      • 2019-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-11
      • 1970-01-01
      • 2019-02-24
      相关资源
      最近更新 更多