F.M
F.M

Reputation: 1909

Environment Variable not loading with load_dotenv() in Linux

I'm trying to make a discord bot, and when I try to load a .env with load_dotenv() it doesn't work because it says

Traceback (most recent call last):
  File "/home/fanjin/Documents/Python Projects/Discord Bot/bot.py", line 15, in <module>
    client.run(TOKEN)
  File "/home/fanjin/.local/lib/python3.8/site-packages/discord/client.py", line 708, in run
    return future.result()
  File "/home/fanjin/.local/lib/python3.8/site-packages/discord/client.py", line 687, in runner
    await self.start(*args, **kwargs)
  File "/home/fanjin/.local/lib/python3.8/site-packages/discord/client.py", line 650, in start
    await self.login(*args, bot=bot)
  File "/home/fanjin/.local/lib/python3.8/site-packages/discord/client.py", line 499, in login
    await self.http.static_login(token.strip(), bot=bot)
AttributeError: 'NoneType' object has no attribute 'strip

Here's my code for the bot:

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)

And the save.env file: (It's a fake token)

# .env
DISCORD_TOKEN={XXXXXXXX}

Both files are in the same directory, and I even tried to explicitly specify the .env's path with

env_path = Path('path/to/file') / '.env'
load_dotenv(dotenv_path=env_path)

but that also didn't work

Upvotes: 14

Views: 70360

Answers (10)

Daniil_VV
Daniil_VV

Reputation: 56

Surprisingly, in my case some variables were parsed successfully, but some were not. Yes, from the same file.

My solution was to check (and set) encoding to be UTF-8 and not UTF-8 with BOM. I had Notepad++ on target machine, right bottom corner has encoding. After that all were loaded as expected.

Weird unnoticed change happed after copy-pasting .env text from Windows machine to remote Windows Server machine

Insane things can happen.

Upvotes: 0

Asclepius
Asclepius

Reputation: 63484

Going further beyond the prior answer by dpritch, this function attempts to first load normally, then from the current directory. In this way it covers both bases.

import dotenv


def load_dotenv():
    """Load the .env file normally and also from the current directory."""
    dotenv.load_dotenv()
    dotenv.load_dotenv(dotenv.find_dotenv(usecwd=True))

This fixed the issue for me in my environment.

Upvotes: 0

dpritch
dpritch

Reputation: 1279

For me I had to use find_dotenv(usecwd=True) to get things to work. Looking at the source code for find_dotenv, by default it looks at the call stack until it finds a frame whose filename is different from the current script's filename and exists on disk as the starting point. In my case, I was running things as part of a snakemake workflow. I'm not sure why calling this function in a snakemake workflow was throwing things off, but adding the usecwd=True gives me the desired behavior.

So in summary, I'm using the following.

dotenv.load_dotenv(dotenv.find_dotenv(usecwd=True))

Upvotes: 2

questionto42
questionto42

Reputation: 9580

TL:DR

You need to put the full path.

Use

  • either os.path.expanduser('~/Documents/MY_PROJECT/.env')

  • or: load_dotenv('/home/MY_USER/Documents/MY_PROJECT/.env')

and it will work.

Or you change your current working directory in your code editor to where the ".env" file is (which should be the project folder).

Or you open the project folder in the menu of your code editor, this should make the project folder the current working directory.

On Linux, you can also go to the project folder in the terminal and start the code editor from there, type for example codium or whatever you use in the command prompt.

Background

Quote from the other answer

Since, I moved my .env file's inside another subfolder config, then I had to provide the full path to load_dotenv() to make it work.

This gave me the idea of checking the working directory.

Current working directory

os.getcwd() gave me a folder further up the tree. And then I copied the ".env" file into that working directory and it worked.

Changing the working directory depends on your code editor. I use codium, which is the open source version of vscode, then you may follow for example Python in VSCode: Set working directory to python file's path everytime

Full path

You can also put the full path.

Funny enough, I had checked that before coming here, but I copied the path that you get from the terminal, starting with '~/Documents/MY_PROJECT, which does not find the file but does not alert either, any tried environment variables were just empty - just because the ".env" file itself was never read.

Upvotes: 12

Mohamed Ali Hefnawy
Mohamed Ali Hefnawy

Reputation: 29

I changed the key=value instead of key='value' and it worked for me.

>>> from dotenv import load_dotenv, find_dotenv
>>> load_dotenv(find_dotenv())
True

Documentation of dotenv library can be accessed from here: python_dotenv python package website

Upvotes: 0

breadmaker
breadmaker

Reputation: 161

I had a similar issue, and in my case, this solved it:

Instead of doing load_dotenv() I needed to do load_dotenv(override=True). This was because I had set one of the variables from the .env file manually, and so it was not updating with the value set in the .env file.

The parameter override defaults to False. Here is the definition, taken from the dotenv github:

override: Whether to override the system environment variables with the variables
            from the `.env` file.

Upvotes: 16

Conor Quinn
Conor Quinn

Reputation: 31

I had:

variable = 'variable'

changing them to be:

variable=variable

fixed the issue. (removing spaces, remove '')

Upvotes: 3

shubham malik
shubham malik

Reputation: 621

I was facing a similar issue and found out these three possible solutions/reasons:
  1. Check if the syntax in your .env file is correct or not, the original documentation will be the best source - Python Dotenv (sample below)

     DOMAIN=example.org
     ADMIN_EMAIL=admin@${DOMAIN}
     ROOT_URL=${DOMAIN}/app
    
  2. The solution which worked for me, was using find_dotenv() instead of file path inside load_dotenv(), the reason is load_dotenv() doesn't load the .env file properly. find_dotenv() is a function that automatically finds .env file if it's located in the same folder as your code file.

     from dotenv import load_dotenv, find_dotenv
    
     load_dotenv(find_dotenv())
    
  3. You can limit your search to the current project folder using sys.path[1] to make sure you're reading the intended file.

     import sys
     from dotenv import load_dotenv
     load_dotenv(sys.path[1]) #try .path[0] if 1 doesn't work
    

Since, I moved my .env file's inside another subfolder config, then I had to provide the full path to load_dotenv() to make it work.

import sys
from dotenv import load_dotenv
path = sys.path[1]+'/config/.env'  #try .path[0] if 1 doesn't work
load_dotenv(path)

[edited]

Upvotes: 14

BrinkDaDrink
BrinkDaDrink

Reputation: 1798

So this took me a while. My load_dotenv() was returning True.

I had commas after some records which is not correct.

Once I removed the commas the variables were working.

Upvotes: 1

spaceofmiah
spaceofmiah

Reputation: 238

I had same error trying to load my environment configuration on ubuntu 20.04 and python-dotenv 0.15.0. I was able to rectify this using python interpreter which will log out any error encountered while trying to load your environments. Whenever your environment variable is loaded successfully, load_dotenv() returns True.

For me it was an issue with my configuration file (syntax error) that broke the loading process. All i needed to do was to go to my environment variable config file and fix the broken syntax..

Try passing verbose=True when loading your environment variable (from python's interpreter) to get more info from load_dotenv.

Upvotes: 4

Related Questions