I have two files in my Telegram bot called loader.py and start_message.py:
loader.py:
from aiogram import Bot, Dispatcher
import environ
from environment import TOKEN
bot = Bot(token=TOKEN)
dp = Dispatcher(bot)
loader.py works perfectly well and the environment variable imports there without raising errors. However, when I try to pass a variable "bot" to the "start_message.py" file:
from aiogram import types
from loader import bot, dp
@dp.message_handler(commands=["start"])
async def send_start_message(message: types.Message):
await bot.send_message(message.chat.id, "Hello!")
I receive the following:
File ~/***/venv/lib/python3.10/site-packages/environ/environ.py:279 in get_value
raise ImproperlyConfigured(error_msg)
ImproperlyConfigured: Set the TOKEN environment variable
It means that the value for TOKEN is not set, although it was set in another file. I tried adding the following lines to the code in start_message.py to initialize the TOKEN variable required for "bot" again:
import environ
env = environ.Env(DEBUG=(bool, False))
environ.Env.read_env(env_file="data/.env")
But the same error kept appearing for some reason. Only when I define bot in start_message.py it works, but it's not what I want to do for every handler file.
The file that is meant to execute the script is main.py. It raises no errors, but the bot isn't responding to the command /start. When debugging, I identified a problem in start_message.py.
main.py:
from aiogram import executor
import nest_asyncio
nest_asyncio.apply()
if __name__ == "__main__":
from handlers import dp
executor.start_polling(dp)
notify_admins.py:
from loader import bot, dp
from aiogram import types
from datetime import datetime
from environment import admin_chat
admin_chat = int(admin_chat)
@dp.message_handler(commands=["start"])
async def send_startup_message_to_admins(message: types.Message):
await bot.send_message(admin_chat, f"[{datetime.now()}] Bot was started by" \
f"@{message.from_user.username}, " \
f"ID: {message.from_user.id}")
environment.py:
import environ
import pathlib
env = environ.Env(DEBUG=(bool, False))
current_dir = pathlib.Path(__file__).resolve().parent
env_file = pathlib.Path(current_dir, "./data/.env")
with open(env_file, 'r') as fd:
environ.Env.read_env(env_file=fd)
TOKEN = env("TOKEN")
admin_chat = env("admin_chat")
The file hierarchy is the following:
my_project
├──__pycache__
├── .spyproject
├──core
│ ├──__init__.py
│ ├──functions
│ │ └──__init__.py
│ │ └──notify_admins.py
│ └──handlers
│ └──__init__.py
│ └──start_message.py
├──data
│ └──.env
├──venv
├──environment.py
├──loader.py
└──main.py
Full error traceback:
runfile('/home/user/***/handlers/start_message.py', wdir='/home/user/***/handlers', current_namespace=True)
Traceback (most recent call last):
File ~/***/venv/lib/python3.10/site-packages/environ/environ.py:275 in get_value
value = self.ENVIRON[var]
File /usr/lib/python3.10/os.py:679 in __getitem__
raise KeyError(key) from None
KeyError: 'TOKEN'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File ~/***/venv/lib/python3.10/site-packages/spyder_kernels/py3compat.py:356 in compat_exec
exec(code, globals, locals)
File ~/***/handlers/start_message.py:9
from loader import bot, dp
File ~/***/loader.py:14
bot = Bot(token=env("TOKEN"))
File ~/***/venv/lib/python3.10/site-packages/environ/environ.py:125 in __call__
return self.get_value(var, cast=cast, default=default, parse_default=parse_default)
File ~/***/venv/lib/python3.10/site-packages/environ/environ.py:279 in get_value
raise ImproperlyConfigured(error_msg)
ImproperlyConfigured: Set the TOKEN environment variable
I'm not sure what the problem is, but you can try the following code
env = environ.Env(DEBUG=(bool, False))
current_dir = pathlib.Path(__file__).resolve().parent
env_file = pathlib.Path(current_dir, "./data/.env")
with open(env_file, 'r') as fd:
environ.Env.read_env(env_file=fd)