pythonpython-moduleexternal-script

why isn't this external Python script reading inside its local directory?


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

token_request.py

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.

api_ingestor.py

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?


Solution

  • 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.