Reputation: 35
I am using python 3.7.1 and have a structure like these in my project
project/
├── plugins
│ ├── __init__.py
│ └── plugin_one
│ ├── __init__.py
│ ├── process_json.py
│ └── data
│ └── cities
│ └── paris.json
│ └── new_york.json
└── test1.py
when I write the "process_json.py" I read the json files from the "data/cities" directory one by one and print out json string.
# do_plugin_one.py
import json
import os
def process_json_string():
file_path = 'data/cities'
for filename in os.listdir(file_path):
if filename.endswith('.json'):
with open(os.path.join(search_path, filename)) as f:
print(json.load(f))
process_json_string()
# output is a json string
If I run this script file directly, it works fine. But what I am trying to achieve is to import process_json.py to test1.py like this:
# test1.py
from plugins.plugin_one.process_json import process_json_string
process_json_string()
and when I tried to do so I got:
FileNotFoundError: [WinError 3] The system cannot find the path specified: 'data/cities'
If I understand it correctly, when imported by the "test1.py", the working path is at where "test1.py" is. So I tried:
# process_json.py
...
def process_json_string():
file_path = 'plugins/plugin_one/data/cities'
...
And it finally works. However, I'd like to keep the file to be able to run separately. After searching through docs and pages I still have no clue how to achieve this. I've even tried:
# process_json.py
...
file_path = 'plugins/plugin_one/data/cities'
...
if __name__ == '__main__':
file_path = 'data/cities'
...
I don't think something like this is optimal though.
I have also tried to use relative path but still no luck. Any help would be appreciated! Thanks!
Upvotes: 0
Views: 772
Reputation: 2703
You're using relative path. While running a python project, the present working directory is considered to be the directory of the file you run.
So, when you run process_json.py
directly, it searches data/cities
in project/plugins/plugin_one
, and when you import process_json.py
in test1.py
, it searches data/cities
in project/
. If you use absolute path, you'll not have this problem.
But, in most cases, you don't want to put absolute path directly, so you can just join directory name of __file__
to data/cities
, and you'll get absolute path:
file_path = os.path.join(os.path.dirname(__file__), 'data', 'cities')
Upvotes: 1
Reputation: 12221
If you want a path relative to process_json.py, you could use the file attribute of that module, and build the path from there:
# process_json.py
import os
datadir = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'data', 'cities')
Of course, you may also consider moving your data directory somewhere else on the file system, not in the package itself (on *nix, somewhere under share/
could be good), and use an environment variable to set the path as necessary.
Upvotes: 0