7
\$\begingroup\$

I've got a Python script which is meant to launch several other shell scripts with the appropriate setup and parameters. I construct the file paths from other variables so that it's easier to change one setting and have it apply everywhere, rather than hardcoding everything.

So, for example:

HOME_DIRECTORY = os.path.dirname(os.path.realpath(__file__))
ONHAND_ACC_NAME = 'onhand_accuracy'
SHRINK_NAME = 'shrink'
SHELL_SCRIPT_EXTENSION = '.ksh'
CONFIG_FILE_EXTENSION = '.conf'
ONHAND_ACC_SHELL_SCRIPT = HOME_DIRECTORY + '/' + ONHAND_ACC_NAME + SHELL_SCRIPT_EXTENSION
SHRINK_SHELL_SCRIPT = HOME_DIRECTORY + '/' + SHRINK_NAME + SHELL_SCRIPT_EXTENSION
ONHAND_ACC_CONFIG_FILE = HOME_DIRECTORY + '/' + ONHAND_ACC_NAME + CONFIG_FILE_EXTENSION
SHRINK_CONFIG_FILE = HOME_DIRECTORY + '/' + SHRINK_NAME + CONFIG_FILE_EXTENSION

These are all constants defined at the top of the script. (Feel free to tell me a more Pythonic way to do this than constants, as well. I've heard before that "Python should have no constants at all", though I'm not sure how accurate or purist that is.)

In Java, I would do something much cleaner, like use an enum to generate appropriate file paths as needed:

public enum FileType {
 SHELL_SCRIPT (".ksh"),
 CONFIGURATION (".conf");
 private static final String HOME_DIRECTORY = "/path/to/scripts";
 private static final String FILE_SEPARATOR = FileSystems.getDefault().getSeparator();
 private final String extension;
 private FileType(String extension) {
 this.extension = extension;
 }
 public String getFilePath(String name) {
 return HOME_DIRECTORY + FILE_SEPARATOR + name + extension;
 }
}

Then I could simply invoke this whenever I wanted to and get a file path, rather than hardcoding them as constants, like so:

FileType.SHELL_SCRIPT.getFilePath("onhand_accuracy");

Any similar tips on how I can improve this practice/technique in Python? I know I could have a similar function in Python that uses a lot of if/elif on a string input, but that still seems much dirtier than an enum, since the calling code can pass in whatever it wants for that string.

(In the Java, I would probably also have an enum for the associated Script, but that would clutter up my example.)

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Mar 27, 2014 at 13:32
\$\endgroup\$
1

2 Answers 2

5
\$\begingroup\$

For something similar to your Java solution, you could have this in filetype.py:

import os.path
class FileType(object):
 HOME_DIRECTORY = "/path/to/scripts"
 def __init__(self, extension):
 self.extension = extension
 def file_path(self, name):
 return os.path.join(self.HOME_DIRECTORY, name + self.extension)
SHELL_SCRIPT = FileType(".ksh")
CONFIGURATION = FileType(".conf")

Then the usage would be

import filetype
filetype.SHELL_SCRIPT.file_path("onhand_accuracy")
answered Mar 27, 2014 at 15:11
\$\endgroup\$
2
  • \$\begingroup\$ That's awesome. Is this a "Pythonic" way to do it, though, or just an analogy to my Java implementation? I like it, either way, but I'd like to also learn how a normal/expert Python developer would go about tackling the problem. \$\endgroup\$ Commented Mar 27, 2014 at 17:54
  • \$\begingroup\$ @JeffGohlke You didn't give much context in your question. I would probably start by using os.path.join where the path is needed, and if I find repeating myself, look for the proper place to store it. \$\endgroup\$ Commented Mar 27, 2014 at 19:24
3
\$\begingroup\$

You could make a module with two global variables and a class the globals starting as:

HOME_DIRECTORY = None
EXTENSIONS = dict(
 SHELL_SCRIPT = '.ksh',
 CONFIG_FILE = '.conf',
 STORE_FILE = '.someextension'
)

And a class that has one static method to set the home directory

If you make a class and there is no set home directory you get an error. You also get an error if the file type is unknown

class CustomPath(object):
 __file_name = str()
 __file_type = str()
 file_name = str()
 file_type = str()
 file_extension = str()
 def __init__(self, file_name, file_type):
 if HOME_DIRECTORY is None:
 raise Exception("Please set the Home Directory")
 self.file_name = self.__file_name = file_name
 if not file_type in EXTENSIONS.keys():
 raise Exception("Unsupported file type")
 self.file_type = self.__file_type = file_type
 self.file_extension = EXTENSIONS[self.__file_type]
 def __repr__(self):
 return HOME_DIRECTORY + '/' + self.__file_name + EXTENSIONS[self.__file_type]
 def __str__(self):
 return self.__repr__()
 @staticmethod
 def SetHomeDirectory( new_path):
 global HOME_DIRECTORY
 HOME_DIRECTORY = new_path

Usage example:

>>> CustomPath.SetHomeDirectory("C/scripts")
>>> my_file = CustomPath("script_a","SHELL_SCRIPT")
>>> my_file
C/scripts/script_a.ksh
>>> str(my_file)
'C/scripts/script_a.ksh'
>>> my_file.file_name
'script_a'
>>> my_file.file_type
'SHELL_SCRIPT'
>>> my_file.file_extension
'.ksh'
>>> 
answered Mar 27, 2014 at 14:57
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.