Can I use an alias to execute a program from a python script

Max picture Max · Jul 28, 2011 · Viewed 13.4k times · Source

I am almost brand new to python scripting, so please excuse any stupid questions, but any help anyone can give would be much appreciated.

I am trying to write a python script for other people to use, and in it I need to call a program that I won't always know the path to. To get around that, I ask the user to provide the path to the program, which will work, but I don't want users to have to provide the path EVERY time they run the script so I have been trying to set up a bash alias by having the script add to the ~/.profile and ~/.bashrc files.

I can then use the alias to run the program from an interactive bash shell, but when the script tries to run it, I get a "command not found" error...

I have tried re-sourcing the .bashrc file and using the "shopt -s expand_aliases" command with no luck.

My ~/.bashrc looks like this:

alias nuke='/Applications/Nuke6.2v4/Nuke6.2v4.app/Contents/MacOS/Nuke6.2v4'

And the piece of the script looks like this:

os.system('source .bashrc')
os.system('shopt -s expand_aliases')
os.system('nuke -x scriptPath')

But once the script gets up to this point, it returns:

sh: nuke: command not found

Am I doing something wrong or is there another way I can permanently store the path to a program?

Answer

FredL picture FredL · Jul 28, 2011

The module you want is subprocess.

A quick fix to your problem is to use the subprocess module, like so:

import subprocess
sp = subprocess.Popen(["/bin/bash", "-i", "-c", "nuke -x scriptpath"])
sp.communicate()

This is equivalent to calling:

nuke -x scriptpath

from the bash shell. The -i flag tells bash to behave as though it's an interactive session (and use the ~/.bashrc file)

BUT, you should be really really careful you're not opening yourself up to any shell injection (for instance, if this command is called from a CGI page)

For quick scipts that users invoke directly from the shell they probably can't do any more damage than they could with general shell access, but if this script is called by a web page a malicious user could pass something a bit like "rm -dfr ~/ &" as the program.*

If the number of executables is small, you might be better off either naming them in the script:

PROGRAMS = {"nuke": "/path/to/nuke"
                "foo" : "/path/to/foo" }

# Parse command line args
program = sys.argv[1] 

sp = subprocess.Popen([PROGRAMS[program], "other", "arguments", "to", "program"])

*This might not work exactly like this, but you get the idea