thinkingmonster
thinkingmonster

Reputation: 5433

How to handle OS errors in python

I am trying to create linux groups using python.Below is function for creating groups.

def createGroups(self):
        adminGroupCommand="groupadd "+ self.projectName+'admin'
        userGroupCommand="groupadd "+ self.projectName+'user'
        try:
            os.system(adminGroupCommand)
        except OSError as err:
            print("group already exists: "+adminGroupCommand)
        try:
            os.system(userGroupCommand)
        except OSError as err:
            print("group already exists: "+userGroupCommand)

The function is successfully creating groups.But if i run the same again it gives below output when run,

groupadd: group 'akphaadmin' already exists
groupadd: group 'akphauser' already exists

Its not printing my custom message in "except"block.How can i force the function to print custom message when creating groups if they already exists.

Upvotes: 0

Views: 760

Answers (1)

skyking
skyking

Reputation: 14394

The function os.system does not report errors from the command line in that way. If you're lucky you'll get the return code (that should be zero on success), but you cannot rely on that according to the documentation.

Instead the documentation recommends to use the subprocess module instead:

def createGroups(self):
    adminGroupCommand="groupadd "+ self.projectName+'admin'
    userGroupCommand="groupadd "+ self.projectName+'user'
    try:
        subprocess.check_call(adminGroupCommand, shell=True)
    except subprocess.CalledProcessError:
        print("group already exists: "+adminGroupCommand)
    try:
        subprocess.check_call(userGroupCommand, shell=True)
    except subprocess.CalledProcessError as err:
        print("group already exists: "+userGroupCommand)

The CalledProcessError has an attribute returncode that you can examine if the groupadd command has different return codes for different causes of failure.

Also note that shell=True means that you rely on the command interpreter to forward the return code (which may not always the case). Instead you could call the command directly:

adminGroupCommand=["groupadd", self.projectName, 'admin']
...
try:
    subprocess.check_call(adminGroupCommand)

...which also has the benefit that if self.projectName contains spaces, asterisks (or other characters that the command line interpreter might interpret) they will be sent to the command in unmodified form (as single command line argument).

Another benefit in using subprocess is that you can control where the output of the command is being directed. If you want to discard stderr or stdout you can redirect it to /dev/null without relying on a shell to do that for you:

subprocess.check_call(adminGroupCommand, stderr=os.devnull, stdout=os.devnull)

There are also possibility to redirect to subprocess.PIPE which allows your python code to read the standard output or standard error from the subprocess.

Upvotes: 1

Related Questions