Search code examples
pythonfilepathlib

How to create a separate file inside each folder using pathlib in python?


Here is a code that randomly writes to a file with filename random1.txt, random2.txt, and so on, based on the number of files given by the user. I'm using pathlib to create directories.

I want to move these files to each of the directories when I run the script.

For example: When the user gives input 2 for "Enter the number of iterations needed" prompt, the script should generate Sample1 folder and random1.txt should be inside Sample1 folder and Sample2 folder should have random2.txt.

import os, glob, shutil
import random, getpass
from pathlib import Path

def sample() -> None:
    username = getpass.getuser()
    number_of_iteration = int(input("Enter the number of iterations needed\n"))
    for i in range(1, number_of_iteration + 1):
        file_name = f"randomfile{i}" + '.txt'
        with open('C:/Users/{0}/PycharmProjects/SampleProject/{1}'.format(username, file_name), 'w') as f:
            list_of_something = [something1, something2, something3]
            random_generator_of_something = random.choice(list_of_something)
            for key, value in random_generator_of_something.items():
                        #does something
                    #writes something to the random file.txt
        with open('C:/Users/{0}/PycharmProjects/SampleProject/{1}'.format(username, file_name), 'a') as f:
                    #writes something to the random file.txt
        Path("C:/Users/{0}/PycharmProjects/SampleProject/Sample{1}".format(username, i)).mkdir(parents=True,
                                                                                                         exist_ok=True)

something1 = {
    'a' : 'b'
}

something2 = {
    'c' : 'd'
}

something3 = {
    'x' : 'y'
}

Solution

  • The preferable way would be to just make a directory first and then making the files directly there.

    I also suggest storing the file or directory path instead of remaking it each time.

    Note: a common beginner mistake is to try to define an object and do something like mkdir here on the same line. But we want to store the object, not result of the method - and mkdir returns None - so those need to be two lines.

    def sample() -> None:
        username = getpass.getuser()
        number_of_iteration = int(input("Enter the number of iterations needed\n"))
        for i in range(1, number_of_iteration + 1):
            my_dir = Path(f"C:/Users/{username}/PycharmProjects/SampleProject/Sample{i}")
            my_dir.mkdir(parents=True, exist_ok=True)
            file_name = f"randomfile{i}.txt"
            with (my_dir / file_name).open('w') as f:
                list_of_something = [something1, something2, something3]
                random_generator_of_something = random.choice(list_of_something)
                for key, value in random_generator_of_something.items():
                            #does something
                        #writes something to the random file.txt
            with (my_dir / file_name).open('a') as f:
                        #writes something to the random file.txt
    

    Now, explanation of magic I did beside making the directory:

    Path class allows creating new paths using / operator (click for docs) - great for appending file names to directories, so I made the (dir / file_name).

    Moreover, Path has a method .open (click for docs) that basically behaves like builtin open. And builtin open can take a path object anyways (since python 3.6, pathlib.PurePath - from which pathlib.Path inherits - implements os.PathLike), so those 3 behave the same:

    • open(my_path_object, mode)
    • open(str(my_path_object), mode)
    • my_path_object.open(mode)