Lets say that you're writing a script to do some post-processing of a deposition run. You've recorded a script to contour the output grid, save some images, and export some data. The problem is that output files (e.g. image files) have the same name in each folder where you've run the script since the names are hardwired into the macro.
The project is organised as follows.
One thing that we could do is to take the directory names, and use those to help name the output files from the macro, instead hard wiring filenames. To do this we need to get the name of the working and parent folder(s) and create a file name from them.
In Python, this information can be gathered from the os module. To get the name of the current (working) directory, we use the function os.getcwd().
1 2 3 4 |
import os
full_path = os.getcwd()
print full_path
|
In Line 1, the os module is imported. The path to the current working directory is assigned to the variable fill_path, and then in Line 4, the path is printed to the output window.
Sometimes, when you get the path it may include a mixture of forward slashes and backslashes as path separators. We can fix this and ensure a consistent ordering by using function from the os.path module called normpath. This will ensure that consistent directory separators are used.
1 2 3 4 5 |
import os
full_path = os.getcwd()
path = os.path.normpath(full_path)
print path
|
The output should be something like:
1 |
D:\Muk3D\Training\TestProject\ooze\scenario1\2019\Q4
|
Next step is to split the path up into its component directories. The variable path (Line 4 above) is simply a string. In Python, the string class has a method called split that will split the string wherever the user specified separator is found. In our case we want to use the path separator character (the backslash) to break the path into tokens. Rather than specify a backslash, we can use the os.sep constant (which in this case is a backslash).
1 2 3 4 5 6 7 8 |
import os
full_path = os.getcwd()
path = os.path.normpath(full_path)
path_tokens = path.split(os.sep)
print path_tokens
|
['D:', 'Muk3D', 'Training', 'TestProject', 'ooze', 'scenario1', '2019', 'Q4']
This is a list comprised of the individual directory strings. Depending on the number of folders we are using to name our files, we need to extract the right values and construct a name from them. For this example, we'll use the last 3 tokens (it wouldn't be useful to use some of the earlier ones since they'll be the same for every deposition scenario).
To access the last 3 tokens we can use the list index notation that accesses values based on their place relative to the end of the list. An example of this is shown below:
1 2 3 4 |
path_tokens = ['D:', 'Muk3D', 'Training', 'TestProject', 'ooze', 'scenario1', '2019', 'Q4']
path_tokens[-1] = 'Q4' # Last value
path_tokens[-2] = '2019' # Second last value
|
We want to take some of these tokens and then join them back together into a string, separated by some character, perhaps an underscore. So rather than try and access tokens individually we can just get a list with the last 3 tokens in it. We do that using the notation:
1 2 3 |
path_tokens = ['D:', 'Muk3D', 'Training', 'TestProject', 'ooze', 'scenario1', '2019', 'Q4']
name_tokens = path_tokens[-3:]
|
The -3 says start at the 3rd last element, the : means get elements until either the value specified after the : or if there is no character specified, get all characters to the end of the list. For this example, the name_tokens would comprise the following:
1 |
['scenario1', '2019', 'Q4']
|
All that's left to do is create the name. To do this, we use the string classes join method to take a list of values (our name tokens) and put them into a string separated by underscores.
1 2 3 4 5 6 7 8 |
import os
full_path = os.getcwd()
path = os.path.normpath(full_path)
path_tokens = path.split(os.sep)
print '_'.join(path_tokens[-3:])
|
In Line 8, the path_tokens are joined into a _ separated string, giving the following:
1 |
scenario1_2019_Q4
|
We could then assign this to a variable instead of printing it out, and use it in filename construction, thereby providing unique filenames that also contain good contextual information about what deposition run they represent.
Below shows this script wrapped into a function to make it easier to incorporate in your own scripts (a Python script file is also attached to this article):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import os
def get_folder_contextual_name(levels, separator='_'):
"""
Gets a contextual name comprised of several levels of parent directory names.
levels: (integer) The number of directory tokens (including current directory name) to include in the filename).
separator: (string) A character to use as the separator in the name construction. Default value is underscore.
"""
full_path = os.getcwd()
path = os.path.normpath(full_path)
path_tokens = path.split(os.sep)
return separator.join(path_tokens[-levels:])
print get_folder_contextual_name(3)
|