Ubuntu 22.04.2 - Python 3.10.6
Windows 11 - Python 3.7.9
project_folder/
├── main.py
├── bot/
└── bot.py
└── logger/
└── logger.py
├── .env
└── backup_arguments.txt
import discord
from discord.ext import commands
from dotenv import load_dotenv
import os
from bot.bot import Bot
from logger import logger
#Load environment variables
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
intents = discord.Intents.all()
bot = Bot(command_prefix='!', intents=intents)
@bot.event
async def on_ready():
logger.info(f'Logged in as {bot.user.name}')
@bot.event
async def on_message(message):
await bot.process_commands(message)
bot.run(TOKEN)
import os
import subprocess
from discord.ext import commands
from utils import backup_utils
from logger import logger
#Load environment variables
print(os.getenv('TARGET_CHANNEL_ID'))
TARGET_CHANNEL_ID = int(os.getenv('TARGET_CHANNEL_ID'))
SCRIPT_URL = os.getenv('SCRIPT_URL')
BACKUP_ARGUMENTS_FILE = 'backup_arguments.txt'
DISCORD_TOKEN="token"
TARGET_CHANNEL_ID=12345
SCRIPT_URL="url/to/script"
None
Traceback (most recent call last):
File ".\main.py", line 5, in <module>
from bot.bot import Bot
File "C:\Data\DiscordBotWatcher\watcher\bot\bot.py", line 9, in <module>
TARGET_CHANNEL_ID = int(os.getenv('TARGET_CHANNEL_ID'))
TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'
I have nearly tried everything I can, and I keep getting the same error message. I double and triple checked the .env file, but it seems alright. I tried to specify the path to the .env file, but that didn't make a change.
Outside that project running, it all runs when it's in one .py script. No errors at all. It seems like the Bot class is not able to read the .env data.
Thanks in advance
The problem is your code in bot.py is being evaluated the moment your import of the bot happens in main.py, before load_dotenv()
is executed.
import discord
from discord.ext import commands
from dotenv import load_dotenv
import os
from bot.bot import Bot # <-- evaluation here triggers bot.py to be imported
The evaluation happens up to this point. Then bot.py is imported, which causes the following to be evaluated immediately:
#Load environment variables
print(os.getenv('TARGET_CHANNEL_ID'))
TARGET_CHANNEL_ID = int(os.getenv('TARGET_CHANNEL_ID'))
Currently, load_dotenv()
hasn't been called, so TARGET_CHANNEL_ID is not yet set.
You would need to either perform the import of your Bot class after you call load_dotenv()
or you would need to move this code in bot.py that utilizes the environment variable somewhere else, like within the Bot class's init method (or some other place), so the code isn't being evaluated until after your load_env()
call, like when Bot is instantiated or when you first call some method of Bot.
For example, this will work as you expect:
main.py:
#!/usr/bin/env python
from dotenv import load_dotenv
from bot import Bot
load_dotenv()
if __name__ == '__main__':
bot = Bot()
bot.run()
bot.py:
import os
class Bot:
def __init__(self):
self.variable = os.getenv("MY_VARIABLE")
def run(self):
print(f"{self.variable}")