pythonfilepython-2.x

Create a file within a subdirectory in python


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


Solution

  • 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