Discord机器人 -“属性错误:'NoneType'对象没有'strip'属性。”

8
我是一位新手程序员,我一直在按照这个教程制作Discord机器人。我几乎是直接从教程中复制下面的代码,然后创建了一个.env文件来存储我的身份验证令牌。每次运行代码时,我都会得到下面所述的错误。有什么提示吗?提前感谢!
代码:
import os 

import discord

from dotenv import load_dotenv

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')

client = discord.Client()

@client.event
async def on_ready():
    print(f'{client.user} has connected to Discord!')
client.run(TOKEN)


错误:
Traceback (most recent call last):   File "/Users/XXXXXXXXXXXX/scratch/discordbot/app.py", line 16, in <module>
    client.run(TOKEN)   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/discord/client.py", line 640, in run
    return future.result()   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/discord/client.py", line 621, in runner
    await self.start(*args, **kwargs)   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/discord/client.py", line 584, in start
    await self.login(*args, bot=bot)   File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/discord/client.py", line 442, in login
    await self.http.static_login(token.strip(), bot=bot) AttributeError: 'NoneType' object has no attribute 'strip' 


我知道你不能分享令牌,但你确定在 .env 文件中定义了正确的令牌吗? - sanitizedUser
我非常确定我已经这样做了。基本上看起来像DISCORD_TOKEN = XXXXXXXXXXX...,以便让您了解我的操作。我只是困惑,因为似乎可能存在访问“.env”文件的问题,尽管我已经安装了所有更新的模块。我不太懂,但我想不出还有什么其他可能出错的地方。 - Jake
1
在教程中,DISCORD_TOKEN和它的值之间没有空格,请尝试去掉空格。 - sanitizedUser
9个回答

8
我遵循同样的教程,并遇到了相同的错误。对我来说,问题在于我错误地创建了".env"文件。教程中说:“在bot.py所在的同一目录中创建名为.env的文件:”,这就是我的问题所在。如果您创建一个新的文本文档,粘贴代码,然后使用名称“.env”保存它,您实际上将创建一个名为“.env.txt”的文本文件。
为了解决此问题,请转到保存Python脚本的目录(对我来说,这是C:\Thonny\DiscordBots),然后在该文件夹中右键单击并选择“新建 > 文本文档”。现在不要更改文件名,只需将其命名为“新建文本文档”。打开此文件(应该会在记事本中打开),然后从教程中复制代码(还要记得将你的机器人实际令牌替换为名为{your-bot-token}的占位符变量)。现在,转到“文件 > 另存为”,在文件名字段中输入“ .env”,就像教程中所说的那样;在点击保存之前,还要点击“另存为类型”下拉菜单(应该在“文件名”下方),并将其从默认类型(*.txt)更改为“All Files”。
如果您按照正确的步骤操作,您应该可以在文件浏览器中看到您的“.env”文件,并且“类型”列现在将显示“ENV文件”,而不是“文本文档”。尝试再次运行代码。
这就是帮助我的方法。我理解的是,“load_dotenv()”正在寻找一种ENV类型的文件,而不仅仅是任何名为“.env”的文件(任何类型)。只要将此文件放置在运行脚本的相同目录中,它应该可以正常工作。

3

这个错误是由于无法获取.env文件中的TOKEN值引起的,可以通过以下方式解决-

from dotenv import load_dotenv
load_dotenv('---.env')

对我来说起作用了!!!


1
在您的.env文件中,它是像“BOT_TOKEN={WHAT_EVER_TOKEN}”或其他什么东西吗? 如果是那样,那就是错误的。 正确的方法是“BOT_TOKEN=WHAT_EVER_TOKEN”,只需去掉“{}”。

我知道这个问题,因为我以前遇到过这个问题,而且是完全一样的... 如果那不行,那很可能是IDE或其他什么问题。 - Kimi
只需要令牌本身和“变量”,不应该有其他东西。 - Kimi

1

我在几个论坛上看了一下,然后发现这个 - 救星谢谢!

现在解决了;

load_dotenv('Token.env')
TOKEN = os.getenv('DISCORD_TOKEN')

Token.env;

DISCORD_TOKEN=在此输入令牌


1
错误是由于TOKEN被设置为None,这就是os.getenv('DISCORD_TOKEN')返回的结果,如果变量不存在或存在并且被设置为None
确保你的.env文件在同一个目录下,例如:
.
├── .env
└── bot.py

令牌是一个环境变量,不是Python变量。分配环境变量遵循你使用的 shell 的语法。这意味着在等号周围没有空格。
使用 dotenv 导出变量到你的 shell 时请注意操作顺序(请参阅 readme here):

Python-dotenv 可以使用 POSIX 变量扩展来插值变量。

变量的值是以下列表中定义的第一个值:

  • 环境中该变量的值。
  • .env 文件中该变量的值。
  • 提供的默认值。
  • 空字符串。

确保将变量用 {} 包围,例如 ${HOME},而不是像 $HOME 这样的裸变量,因为裸变量不会被扩展。

给出的例子是:
CONFIG_PATH=${HOME}/.config/foo
DOMAIN=example.org
EMAIL=admin@${DOMAIN}
DEBUG=${DEBUG:-false

由于这个原因,在继续之前,您可能需要清除相关的 shell 变量,因为 dotenv 将尝试使用已定义的变量,而在初始设置时该变量可能被设置为空字符串(例如:unset DISCORD_TOKEN 或使用类似 source ~/.bashrc 的方式重新启动您的 shell)。
为了调试目的,我建议您使用 print(os.getenv('DISCORD_TOKEN')) 来查看这个变量的确切设置。您也可以尝试在环境设置期间查看 load_dotenv(verbose=True) 的输出。

你关于名称的想法是完全正确的 - 我已经更正了。并且我也做了一些调整以确保.env文件中没有空格,但它仍然出现了相同的错误。我尝试了几种不同的写法,但都不成功。 - Jake
把它变成字符串怎么样?(例如 DISCORD_TOKEN="my-token-here" - jacob
刚刚尝试了一下,不幸的是结果还是一样的(顺便感谢您的建议,我真的很感激您的帮助!) - Jake
你能看到 load_dotenv(verbose=True) 的输出吗? - jacob
是的,听起来像是 load_env() 函数调用在寻找你的 .env 文件但找不到它。你的 .env 文件相对于 bot.py 文件在哪里?dotenv 库在这里的 git hub 上:https://github.com/theskumar/python-dotenv/tree/d83c1b65ceab5cf1223c41649a25a142755fe703 - jacob
显示剩余5条评论

0

你需要从.env文件中删除空格。如果你的文件看起来像这样

DISCORD_TOKEN = 1234ABC

它不会接受它。 它需要看起来像这样

DISCORD_TOKEN=1234ABC

0

我遇到了相同的问题,而且我知道如何解决它。基本上由于某种原因,vscode不接受os.getenv(TOKEN)。所以我所做的就是直接将令牌放入client.run(“你的TOKEN在这里”)函数中。


虽然这是一种解决方案,但强烈建议避免直接在生产代码中使用令牌、密码或其他敏感数据。 - b.geisb

0

看起来读取到的令牌是一个 'NoneType' object

因此,如果你使用 client.run(str(TOKEN)) 而不是 client.run(TOKEN),该方法应该能够正确处理令牌,使你的机器人正常工作。


0

我遇到了同样的问题,即load_dotenv()无法找到与我的.py文件位于完全相同文件夹中的.env文件,导致出现错误Attribute Error: 'NoneType' object has no attribute'strip'

我尝试了许多不同的解决方法,包括load_dotenv(find_dotenv()),用os.envrion['TOKEN']代替os.getenv("TOKEN")以及其他人在此堆栈溢出线程中给我们的所有其他修复程序。您可能已经像我一样尝试了这些方法,但没有成功。

为了解决这个问题,我使用了:

load_dotenv(dotenv_path = os.path.abspath(os.getcwd()) + "\DiscordBot\discordbot.env")

这指定了load_dotenv()将加载的确切文件(我认为)。注意os.path.abspath(os.getcwd())。它返回项目文件所在的当前工作目录(getcwd())。在我的情况下,它会返回这个字符串:
F:\dev\Python\YaykobDiscordBot

我的实际.py文件位于更深的另一个文件夹中:"F:\dev\Python\YaykobDiscordBot\DiscordBot\YaykobBot.py",并且在同一个文件旁边是 "F:\dev\Python\YaykobDiscordBot\DiscordBot\discordbot.env",这是我存储令牌的地方。

您可能会注意到,实际上,您只需要给load_dotenv()提供.env文件所在的文件路径即可。在我的情况下,我可以写: load_dotenv(dotenv_path = "F:\dev\Python\YaykobDiscordBot\DiscordBot\discordbot.env"),它将完美地工作。我使用os.path.abspath,因为它可以在我想要从Github克隆我的存储库时工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接