I was doing some API stuff the other day and ran across this (maybe) weird behavior in python. Basically I have a script in a secret folder ./secret_stuff/token_request.py
that constructs and returns a new API access token. Looks something like this
import json
import requests
def generate_token():
url = json.load(open('./secrets.json'))['endpoints']['token'] # reads and stores relevant endpoint for token request from supporting file
data = json.load(open('./secrets.json'))['token_request_data'] # loads token request data from supporting file
r = requests.post(url=url, params=data).json()
return r['access_token']
if __name__ == '__main__':
generate_token()
which runs fine when I execute it using CLI...
i import the external script as a module, then instantiate it at the top of my actual program that works with the api/data etc.
import json
import re
import requests
import secret_stuff.token_request as tr
token = tr.generate_token()
endpoint = json.load(open('./secret_stuff/secrets.json'))['endpoints']['KeyMessageData']
and get FileNotFound
error thrown from the tr.generate_token()
call on the line where it assigns url
as the endpoint from the .json
file in its local directory, which is a subdirectory of the entire project.
The directory structure looks like this:
|
|
/secrets
| |
| |
| --secrets.json
| |
| --token_request.py
|
api_ingestor.py
And if I make this change to token_request.py
in the line where the url
and data
are assigned:
def generate_token():
url = json.load(open('./secret_stuff/secrets.json'))['endpoints']['token'] # reads and stores relevant endpoint for token request from supporting file
data = json.load(open('./secret_stuff/secrets.json'))['token_request_data'] # loads token request data from supporting file
then it works in api_ingestor.py
! No FileNotFound
error!
But now it doesn't work by itself when run thru CLI because there is no subdirectory in its local directory..
Anyone want or able to explain this behavior to me?
Your file location will depend on the current working directory when it's executed. Use something like the following to make it always use the directory where the script is located:
import os
secret_file = os.path.join(os.path.dirname(__file__), "secrets.json")
url = json.load(open(secret_file))['endpoints']['token'] # reads and stores relevant endpoint for token request from supporting file
data = json.load(open(secret_file))['token_request_data'] # loads token request data from supporting file
This will use the directory where the script is located instead of the current working directory.
It would be MUCH nicer if you read the JSON into a structure and pulled the elements from it separately rather then have json.load() read the whole file twice.