here's what I do. I have one module for each project that lays out all of the directories, URL's and common file locations in a relative structure, using pathlib.
Here's a sample for a geocoding project:
the module is named GeoPaths.py and is imported by just about every other module in the project.
A neat feature of using something like this, is that you can run it on it's own in a copy of the project to
immediately set up your directory structure (it will create missing directories, but will leave already existing
directories alone):
GeoPaths.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
import os
from pathlib import Path
class GeoPaths:
def __init__( self , depth = 0 ):
dir_depth = abs (depth)
os.chdir(os.path.abspath(os.path.dirname(__file__)))
self .homepath = Path( '.' )
while dir_depth:
self .homepath = self .homepath / '..'
dir_depth - = 1
rootpath = self .homepath / '..'
self .docspath = rootpath / 'docs'
self .docspath.mkdir(exist_ok = True )
self .testspath = rootpath / 'tests'
self .testspath.mkdir(exist_ok = True )
self .datapath = rootpath / 'data'
self .datapath.mkdir(exist_ok = True )
self .csvpath = self .datapath / 'csv'
self .csvpath.mkdir(exist_ok = True )
self .htmlpath = self .datapath / 'html'
self .htmlpath.mkdir(exist_ok = True )
self .jsonpath = self .datapath / 'json'
self .jsonpath.mkdir(exist_ok = True )
self .MasterAddressPath = self .datapath / 'MasterAddressDatabase'
self .MasterAddressPath.mkdir(exist_ok = True )
self .prettypath = self .datapath / 'pretty'
self .prettypath.mkdir(exist_ok = True )
self .tmppath = self .datapath / 'tmp'
self .tmppath.mkdir(exist_ok = True )
self .osmpath = self .datapath / 'osm'
self .osmpath.mkdir(exist_ok = True )
self .geofabrik_datapath = self .osmpath / 'GeofabrikAndCensus'
self .geofabrik_datapath.mkdir(exist_ok = True )
self .geofabrikjson = self .jsonpath / 'GeofabrikLinks.json'
if __name__ = = '__main__' :
GeoPaths()
|
Before running the script, my directory structure for a new project looks like this:
Output:
├── src
│ └── GeoPaths.py
└── venv
...
After running GeoPaths.py directory structure looks like this:
1 2 |
$ . . / venv / bin / activate
(venv)$ python src / GeoPaths.py
|
Output:
.
├── data
│ ├── csv
│ ├── html
│ ├── json
│ ├── MasterAddressDatabase
│ ├── osm
│ │ └── GeofabrikAndCensus
│ ├── pretty
│ └── tmp
├── docs
├── src
│ └── GeoPaths.py
├── tests
└── venv
...
Now, assume you have a module named MyModule.py in the src diretory, and you want to open a json file named sillyfile.json.
here's the code that would do that:
MyModule.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
from GeoPaths import GeoPaths
import json
class MySillyClass:
def __init__( self ):
self .gpaths = GeoPaths()
self .jsonfile = self .gpaths.jsonpath / 'sillyfile.json'
def create_dict( self ):
sillydict = {
'Cowboys' : '21' ,
'GreenBayPackers' : '7'
}
with self .jsonfile. open ( 'w' ) as fp:
json.dump(sillydict, fp)
def read_it_back( self ):
with self .jsonfile. open () as fp:
read_sillydict = json.load(fp)
for key, value in read_sillydict.items():
print ( f "{key}: {value}" )
def main():
mcc = MySillyClass()
mcc.create_dict()
mcc.read_it_back()
if __name__ = = '__main__' :
main()
|
you can actually run this
results:
Output:
Cowboys: 21
GreenBayPackers: 7
The depth attribute in GeoPaths.py can be used when code in in a subdirectory of src.
Increment by on for each sublevel, and paths will automatically be adjusted for all source code in that subdirectory.