How to use python-dotenv's "find_dotenv" method
Question:
I’ve pip-installed the python-dotenv module and am trying to use it as follows. I’ve created a directory test_dotenv
with the following tree:
.
├── config.env
└── test_dotenv_subdir
└── test_dotenv.py
The config.env
file is simply an empty file, while test_dotenv.py
contains the following:
import dotenv
found_dotenv = dotenv.find_dotenv()
print(found_dotenv)
However, if I run this script using python test_dotenv.py
, I find that nothing gets printed; that is, found_dotenv
is an empty string (''
).
Am I missing something about how to use this method? As far as I can tell, here is the relevant part of the source code:
def _walk_to_root(path):
"""
Yield directories starting from the given directory up to the root
"""
if not os.path.exists(path):
raise IOError('Starting path not found')
if os.path.isfile(path):
path = os.path.dirname(path)
last_dir = None
current_dir = os.path.abspath(path)
while last_dir != current_dir:
yield current_dir
parent_dir = os.path.abspath(os.path.join(current_dir, os.path.pardir))
last_dir, current_dir = current_dir, parent_dir
def find_dotenv(filename='.env', raise_error_if_not_found=False, usecwd=False):
"""
Search in increasingly higher folders for the given file
Returns path to the file if found, or an empty string otherwise
"""
if usecwd or '__file__' not in globals():
# should work without __file__, e.g. in REPL or IPython notebook
path = os.getcwd()
else:
# will work for .py files
frame_filename = sys._getframe().f_back.f_code.co_filename
path = os.path.dirname(os.path.abspath(frame_filename))
for dirname in _walk_to_root(path):
check_path = os.path.join(dirname, filename)
if os.path.exists(check_path):
return check_path
if raise_error_if_not_found:
raise IOError('File not found')
return ''
It seems like os.path.exists(check_path)
keeps on returning False
, so that the in the end an empty string is returned. Why is this not working as intended?
Answers:
The dotenv
package looks for a file that is literally called .env
when you call find_dotenv
rather than looking for files like .env
. (e.g. config.env
)
You can make your code find the desired file by passing the filename to find_dotenv
, i.e.
import dotenv
found_dotenv = dotenv.find_dotenv('config.env')
print(found_dotenv)
One possible reason for that can be *.pyc files from another host stored in the project.
i.e. in my case, I copied the content of my repo into the container and start getting this error:
.venv/lib/python3.7/site-packages/dotenv/main.py:257: in _walk_to_root
raise IOError('Starting path not found')
E OSError: Starting path not found
I fixed it by running:
find . -name '*.pyc' | xargs rm -frv {} ;
To use the find_dotenv to search in the current working directory, try giving the usecwd argument as true, as shown below:
dotenv_file = dotenv.find_dotenv(usecwd=True)
dotenv.load_dotenv(dotenv_file)
So this searches for the ‘.env’ file in the current working directory.
I’ve pip-installed the python-dotenv module and am trying to use it as follows. I’ve created a directory test_dotenv
with the following tree:
.
├── config.env
└── test_dotenv_subdir
└── test_dotenv.py
The config.env
file is simply an empty file, while test_dotenv.py
contains the following:
import dotenv
found_dotenv = dotenv.find_dotenv()
print(found_dotenv)
However, if I run this script using python test_dotenv.py
, I find that nothing gets printed; that is, found_dotenv
is an empty string (''
).
Am I missing something about how to use this method? As far as I can tell, here is the relevant part of the source code:
def _walk_to_root(path):
"""
Yield directories starting from the given directory up to the root
"""
if not os.path.exists(path):
raise IOError('Starting path not found')
if os.path.isfile(path):
path = os.path.dirname(path)
last_dir = None
current_dir = os.path.abspath(path)
while last_dir != current_dir:
yield current_dir
parent_dir = os.path.abspath(os.path.join(current_dir, os.path.pardir))
last_dir, current_dir = current_dir, parent_dir
def find_dotenv(filename='.env', raise_error_if_not_found=False, usecwd=False):
"""
Search in increasingly higher folders for the given file
Returns path to the file if found, or an empty string otherwise
"""
if usecwd or '__file__' not in globals():
# should work without __file__, e.g. in REPL or IPython notebook
path = os.getcwd()
else:
# will work for .py files
frame_filename = sys._getframe().f_back.f_code.co_filename
path = os.path.dirname(os.path.abspath(frame_filename))
for dirname in _walk_to_root(path):
check_path = os.path.join(dirname, filename)
if os.path.exists(check_path):
return check_path
if raise_error_if_not_found:
raise IOError('File not found')
return ''
It seems like os.path.exists(check_path)
keeps on returning False
, so that the in the end an empty string is returned. Why is this not working as intended?
The dotenv
package looks for a file that is literally called .env
when you call find_dotenv
rather than looking for files like .env
. (e.g. config.env
)
You can make your code find the desired file by passing the filename to find_dotenv
, i.e.
import dotenv
found_dotenv = dotenv.find_dotenv('config.env')
print(found_dotenv)
One possible reason for that can be *.pyc files from another host stored in the project.
i.e. in my case, I copied the content of my repo into the container and start getting this error:
.venv/lib/python3.7/site-packages/dotenv/main.py:257: in _walk_to_root
raise IOError('Starting path not found')
E OSError: Starting path not found
I fixed it by running:
find . -name '*.pyc' | xargs rm -frv {} ;
To use the find_dotenv to search in the current working directory, try giving the usecwd argument as true, as shown below:
dotenv_file = dotenv.find_dotenv(usecwd=True)
dotenv.load_dotenv(dotenv_file)
So this searches for the ‘.env’ file in the current working directory.