Create a file within a subdirectory in python

Question:

I need to create folders and files as below:

Suppose my current working directory is called ‘working_dir’

I need to create -> working_dir/my_folder/sub_folder/new_file.json

I can create a file in a sub directory as below:

import json
import os

my_details = {
'name': 'John Doe',
'age': 29
}

if not os.path.exists('my_folder'):
  os.makedirs('my_folder')

with open('my_folder/personal.json', 'w') as json_file:
  json.dump(my_details, json_file)

Below are my two questions:

  1. How to create directories two level down in one go. I mean using the makedirs syntax, how do I create /my_folder/sub_folder.

  2. Is using makedirs syntax necessary? Can’t I create directories in the statement ‘with open….’ directly. I am getting an error if I remove the makedirs statement from above i.e. it doesn’t create the folder if it doesn’t exist already and thus, doesn’t create the file.

Please note the script should work irrespective of the OS. Also, I am using python 2.7.12

Asked By: T Anna

||

Answers:

To your first point, if you are trying to create folders irrespective of OS, then I would lean towards using os.path.join for folder/file paths:

import os

path = os.path.join(os.getcwd(), 'path', 'to', 'folder')
os.makedirs(path)

Since windows and *nix have different path separators.

Per the documentation:

Super-mkdir; create a leaf directory and all intermediate ones. Works like mkdir, except that any intermediate path segment (not just the rightmost) will be created if it does not exist. This is recursive.

with open(file, 'w') will create a file, not a folder. So you will need to keep your makedirs call ahead of opening the file. You will need to catch an OSError if the folders already exist:

import os

folders = os.path.join('some', 'folder')

os.makedirs(folders)
os.makedirs(folders)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mm92400/anaconda3/envs/27testenv/lib/python2.7/os.py", line 157, in makedirs
    mkdir(name, mode)
OSError: [Errno 17] File exists: 'some/folder'

So in your production code, this would look like:

try:
    os.makedirs(folders)
except OSError:
    # do some logging
    print('folder exists!')

Lastly, I would strongly suggest switching to python3 if you can, python2 is reaching end of life at the end of this year. The python3 implementation of this is much cleaner, since it enables the use of the exist_ok flag:

Super-mkdir; create a leaf directory and all intermediate ones. Works like mkdir, except that any intermediate path segment (not just the rightmost) will be created if it does not exist. If the target directory already exists, raise an OSError if exist_ok is False. Otherwise no exception is raised. This is recursive.

So your code will wind up looking like:

# python3 version
import os

folders = os.path.join('some', 'folder')

os.makedirs(folders, exist_ok=True)
os.makedirs(folders, exist_ok=True)

Negating the need for any checks or try/except, though the try/except could be seen as a bit more explicit

Answered By: C.Nivs
from io import open
import os,json

def make_recur_path(custom_path): 
    try: 
        os.makedirs(custom_path) 
        return True 
    except OSError: 
        return False 
         
my_details = {
'name': 'John Doe',
'age': 29
}

mystrpath="my_folder/sub_folder"

''' Always use os.path functions when you define a path to make it readable.'''

custom_path=os.path.join(os.getcwd(), mystrpath)

def make_recur_path(custom_path): 
    try: 
        os.makedirs(custom_path) 
        return True 
    except OSError: 
        return False 

if make_recur_path(custom_path):
   with open(os.path.join(custom_path,'personal.json'),mode="w", encoding="utf-8") as f_handle:
        json.dump(my_details,f_handle)

I am a mac user so I am unable to check in Windows. Please check and let me know if this works for you.

Answered By: subbu
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.